<div id="root"></div>
const { createGlobalStyle } = styled;

const GlobalStyle = createGlobalStyle`
  :root {
    --theme-background-primary: #151618;
    --theme-primary: #FFFFFF;
  }
  
  html.light {
    --theme-background-primary: #E9EAEC;
    --theme-primary: #151618;
  }

  html {
    background: var(--theme-background-primary);
  }

  html.theming,
  html.theming * {
    transition: all 0.2s linear;
  }
`;

const Button = styled.button`
  padding: 8px 16px;
  color: var(--theme-primary);
  background: none;
  outline: none;
  border-radius: 4px;
  border: 1px solid var(--theme-primary);
  cursor: pointer;
`;

function App() {
  const toggleTheme = () => {
    document.documentElement.classList.add('theming');
    document.documentElement.addEventListener('transitionend', () => {
      if (document.documentElement) {
        document.documentElement.classList.remove('theming');
      }
    }, {once: true});
    document.documentElement.classList.toggle('light');
  };
  
  return (
    <div>
      <GlobalStyle />
      <Button onClick={toggleTheme}>Toggle theme</Button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/react-is/16.13.1/umd/react-is.production.min.js
  4. https://cdnjs.cloudflare.com/ajax/libs/styled-components/5.1.1/styled-components.min.js