Theming with styled-components

31 July, 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);

 


You might also be interested in the following posts:

The whole logic of styled-components can be described in one "feature request": "Let's manage CSS in js alongside with component core code". The logic behind it is sort of obvious - it will give us the dynamic of js inside of CSS and we'll be able to treat styling as part of component code and not store it in a separate file.

The idea is promising, now let's see what are some of the edge cases. And why is that? Because nothing is ideal in the world.

IMO styled-components library has only one problematic warning. It's "Warning: Received true for non-boolean attribute". When I encountered it for the first time it took me some time to figure out what was the problem.