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.