Theming in React
Theming is a fascinating topic and a really important one these days as more and more people add light and dark mode to their sites and companies change the theme of their site or part of their site on specific dates to celebrate occasions such as christmas, pride week etc.
But where do we start when it comes to creating themes? It all starts with the designers. They are the ones who are creating the themes. Each theme should have a list of design tokens that show the theme colors, paddings, margins, fonts, etc. These tokens can be exported from tools such as Figma and then used in a theme component.
In this example I will show you how to do theming in React using Bit, however if you are not using Bit this will still work in any React app and you can install the one Bit component that we are using though npm or yarn. The Theme Provider component from teambit will convert these design tokens from JSON format to usable CSS variables without you having to do any extra work, which is kinda cool.
By using Bit we are making sure our components are fully independent and can be easily installed into any app. If you are not using Bit then you will need to change the import statements to use relative paths to your components. And if you are not using typescript then feel free to change the file extension to .jsx and ignore the schema which is just for type checking.
So lets get started with theming in React.
Step 1: Create your Theme Provider Component
- Create a new theme provider component.
- Add a
theme-schema.tsx
file and include all types for your design tokens.
export interface ThemeSchema { myColorText?: string myFontSize?: string myBorderColor?: string myBorderRadius?: string}
Add a '?' to make the tokens optional so you can use tokens from the default theme as well as override any tokens the theme wants to change.
- Add a
default-theme-tokens.tsx
file which should include all design tokens and values for your default theme.
import { ThemeSchema } from './theme-schema';
export const defaultTheme: ThemeSchema = {
myColorBackground: '#ffffff',
myColorText: 'purple',
myFontSize: '26px',
myBorderColor: 'purple',
myBorderRadius: '5px',
};
- Install the
ThemeProvider
component from teambit.
bit install @teambit/base-react.theme.theme-provider// ornpm install @teambit/base-react.theme.theme-provider
- Import the
createTheme
function from teambit's Theme Provider component and thedefaultTheme
from thedefault-theme-tokens
file in yourtheme-provider.tsx
file. Create your theme using thecreateTheme()
function passing into it thedefaultTheme
as the value for theme.
import { createTheme } from '@teambit/base-react.theme.theme-provider'import { defaultTheme } from './default-theme-tokens'export const Theme = createTheme({ theme: defaultTheme})
You supply the design tokens directly to the createTheme function and it does the rest for you to convert the tokens to usable css (both in modules and directly in your css).
- Add compositions, tests and docs.
Step 2: Use your Theme Provider
- Import the Theme from the ThemeProvider component you created.
import { Theme } from '@learn-bit-react/theming.themes.theme-provider'
- Wrap all components in the theme provider to see the theme applied to your components.
import React from 'react'import { Theme } from '@learn-bit-react/theming.themes.theme-provider'import { Button } from '@learn-bit-react/theming.example.button'export const MyApp = () => { return ( <Theme.ThemeProvider> <Button>Hello</Button> </Theme.ThemeProvider> )}
Button using Default Theme
You can install and use the Button component from this demo as an example or create your own and add some styles to it using css variables.
Step 3: Create a Dark Theme Component
- Create a new theme component.
bit create react themes/dark-theme
- Add a
dark-theme-tokens.tsx
file with the design tokens and values you want to override from the default theme.
import type { ThemeSchema } from '@learn-bit-react/theming.themes.theme-provider'export const darkTheme: ThemeSchema = { myColorBackground: '#000', myColorText: 'red', myBorderColor: 'red'}
Import the ThemeSchema for type checking.
- Import the
Theme
from the the theme provider component you just created as well as thedarkTheme
from thedark-theme-tokens
file.
import React from 'react';
import { Theme } from '@learn-bit-react/theming.themes.theme-provider';
import { darkTheme } from './dark-theme-tokens';
export const DarkTheme = ({ children }) => {
return (
<Theme.ThemeProvider overrides={darkTheme}>
{children}
</Theme.ThemeProvider>
);
};
Add the darkTheme to the overrides prop of the theme provider.
- Make sure your index file is exporting both the
DarkTheme
component as well as thedarkTheme
tokens.
export { DarkTheme } from './dark-theme';
export { darkTheme } from './dark-theme-tokens';
- Add compositions, tests and docs.
Step 4: Use your Theme in a Component
- Import the Theme from the ThemeProvider component you created as well as the DarkTheme and any components you want to render.
import React from 'react'import { Theme } from '@learn-bit-react/theming.themes.theme-provider'import { DarkTheme } from '@learn-bit-react/theming.themes.dark-theme'import { Button } from '@learn-bit-react/theming.example.button'
Wrap all components in the Theme Provider component and use the overrides prop to change the theme to darkTheme.
export const MyApp = () => { return ( <Theme.ThemeProvider overrides={darkTheme}> <Button>Hello</Button> </Theme.ThemeProvider> )}
Button with Dark Theme applied
Use theme like a wrapper component You can alternatively use the component like this which will work exactly the same as the example above.
export const MyApp = () => { return ( <DarkTheme> <Button>Dark Theme</Button> </DarkTheme> )}
Multiple Themes
You can also use the default theme and have a part of your app be wrapped in a different theme.
export const MyApp = () => { return ( <Theme.ThemeProvider> <Button>Default Theme</Button> {/* A dark themed button inside a default theme */} <DarkTheme> <Button>Dark Theme</Button> </DarkTheme> </Theme.ThemeProvider> )}
Conclusion
And thats how you do theming in React. For more info on how the components work or to learn more on theming and React context check out: