This site has been updated.
Reload to display the latest version?
(click here)

Theming with styled-components

July 31, 2020

Theme can be stored (or generated) in a js file. For instance, we can keep all of them, in ./themes folder and load, while bootstrapping the application.

const loadTheme = themeName => new Promise((resolve, reject) => {
  const resolveResponse = response => resolve(response.default);
  import(`./themes/${themeName}Theme`)
    .then(resolveResponse)
    .catch((err) => {
      const defaultThemeName = 'default';
      if (themeName !== defaultThemeName) {
        console.warn(`Can't load "${themeName}" theme`);
        console.warn(err);
        console.warn(`Trying to load the default theme`);
        return import(`./themes/${defaultThemeName}Theme`)
          .then(resolveResponse);
      }
      throw new Error(err);
    })
    .catch((err) => {
      console.error(err);
      reject(new Error('Theme can\'t be loaded'));
    });
});

Provide theme to the app.

import { render } from 'react-dom';
import { ThemeProvider } from 'styled-components';

// ...

const bootstrapApp = () => {
  loadTheme(configs.theme)
    .then((theme) => {
      render(
        <ThemeProvider theme={theme}>
          <App />
        </ThemeProvider>,
        document.getElementById('app'),
      );
    });
};

Now your theme will be available via this.props.theme of styled-components. Theme property can be anything you defined it to be. In the example below, it’s an object with two properties: infoButtonBgColor and name.

import styled, { withTheme } from 'styled-components';

const InfoButton = styled.button`
  background-color: ${props => props.theme.infoButtonBgColor};
`;

const InfoArea = (props) => {
  const { theme } = props;
  return (
    <div>
      {theme.name}
      <InfoButton>Ok</InfoButton>
    </div>
  );
};

export default withTheme(InfoArea);