Implementation — Part II
🌈 Setting up a centralized theme


💡 Why a centralized theme?
➡️ Design System References
- Typography ( Docs )
- Colors ( Docs )
Configuring the Typography System
To set up the Typography System, navigate to the
src
folder and create a new folder named theme
. Inside this folder, create a new file named typography.js
, so the path would be src/theme/typography.js
. Below are the contents of this file:export default { fontFamily: ["Roboto", "Helvetica", "Arial", "sans-serif"].join(","), fontSize: 14, h1: { fontSize: "6rem", fontWeight: 300, }, h2: { fontSize: "3.75rem", }, h3: { fontSize: "3rem", fontWeight: "400", }, h4: { fontSize: "2.125rem", fontWeight: "normal", }, h5: { fontSize: "2rem", fontWeight: "normal", }, h6: { fontSize: "1.5rem", fontWeight: "normal", }, body1: { fontWeight: "normal", }, body2: {}, button: { fontSize: "1rem", fontWeight: 700, textTransform: "capitalize", }, subtitle1: {}, subtitle2: {}, caption: {}, overline: { fontWeight: 600, }, };
Configuring the Color System
Similarly, within the src/theme directory, create a new file named
palette.js
, resulting in the path src/theme/palette.js
. Below are the contents of this file:
const white = "#fff"; const black = "#000"; const primaryColor = "#ff1b6b"; const primaryLight = "#ffbed4"; const primaryDark = "#9d0159"; const secondaryColor = "#2d2f3c"; const secondaryLight = "#eaecfe"; const secondaryDark = "#0D0F1C"; const RED_PALETTE_KEY = "red"; const BLACK_PALETTE_KEY = "black"; export const PALETTE_KEYS = [RED_PALETTE_KEY, BLACK_PALETTE_KEY]; const redPalette = { [`${RED_PALETTE_KEY}50`]: "#ffe5ee", [`${RED_PALETTE_KEY}100`]: primaryLight, [`${RED_PALETTE_KEY}200`]: "#ff93b7", [`${RED_PALETTE_KEY}300`]: "#ff659a", [`${RED_PALETTE_KEY}400`]: "#ff4282", [`${RED_PALETTE_KEY}500`]: primaryColor, [`${RED_PALETTE_KEY}600`]: "#ed1768", [`${RED_PALETTE_KEY}700`]: "#d71363", [`${RED_PALETTE_KEY}800`]: "#c20c60", [`${RED_PALETTE_KEY}900`]: primaryDark, }; const blackPalette = { [`${BLACK_PALETTE_KEY}50`]: "#f4f6ff", [`${BLACK_PALETTE_KEY}100`]: secondaryLight, [`${BLACK_PALETTE_KEY}200`]: "#dee0f1", [`${BLACK_PALETTE_KEY}300`]: "#cbcdde", [`${BLACK_PALETTE_KEY}400`]: "#858796", [`${BLACK_PALETTE_KEY}500`]: "#5e606e", [`${BLACK_PALETTE_KEY}600`]: "#5e606e", [`${BLACK_PALETTE_KEY}700`]: "#4b4d5b", [`${BLACK_PALETTE_KEY}800`]: secondaryColor, [`${BLACK_PALETTE_KEY}900`]: secondaryDark, }; const warnings = { success: "#72CEC1", caution: "#e9d587", error: "#B00020", danger: "#E52B20", }; export default { primary: { contrastText: white, main: primaryColor, light: primaryLight, dark: primaryDark, }, secondary: { contrastText: white, dark: secondaryDark, main: secondaryColor, light: secondaryLight, }, text: { primary: black, secondary: blackPalette.black500, link: redPalette.red600, info: primaryLight, }, background: { default: white, }, error: { contrastText: white, dark: warnings.danger, main: warnings.error, light: warnings.caution, }, disabled: { contrastText: white, dark: blackPalette.black700, main: blackPalette.black50, }, ...redPalette, ...blackPalette, };
Consolidate both systems
Finally, create an index file to consolidate both systems under
src/theme
. Name this file index.js
and ensure it includes the following content:import { createTheme } from '@mui/material' import palette from './palette' import typography from './typography' export default createTheme({ palette, typography, })
Adding a New Theme in Storybook
Navigate to
src/.storybook/preview.js
and replace its contents with the following:import CssBaseline from "@mui/material/CssBaseline"; import { ThemeProvider } from "@mui/material/styles"; import theme from "theme"; const preview = { parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }, decorators: [ (Story) => ( <ThemeProvider theme={theme}> <CssBaseline /> <Story /> </ThemeProvider> ), ], }; export default preview;
Creating Stories for Your New Systems
To simplify this process, download and extract the contents of the provided folder into your
src/stories
directory. After restarting Storybook, you will be able to view the changes.Typography Story

Colors Story

Updating the Button Component
With the theme injected, styling the Button component becomes much simpler.
First, replace the contents of the
Button.styles.js
file with the following:export default { button: { borderRadius: "3rem", }, };
👉 We've removed 50 lines of logic. Give yourself a pat on the back!
Next, make these two tweaks in the
Button.jsx
component:... }) => ( <MuiButton disableElevation={disableElevation} disableFocusRipple={disableFocusRipple} disabled={disabled} fullWidth={fullWidth} variant={variant} size={size} color={color} // 👈 1st change: Add this line sx={styles.button} // 👈 2nd change: Replace the `sx` value with this line {...props} > {children} </MuiButton> ) ...
Now, our
<Button>
utilizes the theme directly for all color variations. Try testing its behavior by adjusting the color
property.