Theme
The Cherry theme is a TypeScript object that defines various aspects of your project. Whether you're working on media queries, spacing sizes, colors, font sizes, or line heights, the Cherry theme has got you covered. Cherry also offers a Figma plugin to extract design tokens - check out the Figma documentation for details.
Wrap your entire application with CherryThemeProvider to ensure all components have access to the theme:
import {
CherryThemeProvider,
theme,
themeDark,
} from "cherry-styled-components";
export default function App({ Component, pageProps }) {
return (
<CherryThemeProvider theme={theme} themeDark={themeDark}>
<Component {...pageProps} />
</CherryThemeProvider>
);
}Cherry exports two ready-made theme objects to start from: theme (light) and themeDark (dark). CherryThemeProvider accepts an optional themeDark prop - dark mode switching only happens when you pass it. The provider also exports a ThemeContext that gives you setTheme and toggleTheme for switching themes programmatically. See the Dark Mode documentation for details.
Theme Object
The theme object is type safe and uses TypeScript. The Theme interface has eight keys: the seven sections below plus an isDark boolean that marks a theme as a dark variant:
export const breakpoints: Breakpoints = {
xs: 0,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1440,
xxxl: 1920,
};
export function mq(minWidth: keyof Breakpoints) {
return `@media screen and (min-width: ${breakpoints[minWidth]}px)`;
}The mq() helper turns a breakpoint key into a min-width media query. Use it inside your styled components to apply styles from that breakpoint upwards:
import styled from "styled-components";
import { mq } from "cherry-styled-components";
const Wrapper = styled.div`
padding: 20px;
${mq("lg")} {
padding: 40px;
}
`;export const spacing: Spacing = {
maxWidth: { xs: "1280px", xxxl: "1440px" },
padding: { xs: "20px", lg: "40px" },
radius: { xs: "6px", lg: "12px", xl: "30px" },
gridGap: { xs: "20px", lg: "40px" },
};export const colors: Colors = {
primaryLight: "#91aec4",
primary: "#4d6f8b",
primaryDark: "#194569",
secondaryLight: "#a4b17b",
secondary: "#5c6e46",
secondaryDark: "#354c2b",
tertiaryLight: "#ebccb9",
tertiary: "#816b5a",
tertiaryDark: "#675445",
grayLight: "#e5e7eb",
gray: "#9ca3af",
grayDark: "#4b5563",
success: "#84cc16",
error: "#ef4444",
warning: "#eab308",
info: "#06b6d4",
dark: "#000000",
light: "#ffffff",
};A dark counterpart, colorsDark, is also exported and used by themeDark. It flips dark/light, swaps the grays for dark-surface values, and brightens the primary palette:
export const colorsDark: Colors = {
primaryLight: "#79C5FF",
primary: "#6198C6",
primaryDark: "#339DF4",
secondaryLight: "#a4b17b",
secondary: "#5c6e46",
secondaryDark: "#354c2b",
tertiaryLight: "#ebccb9",
tertiary: "#816b5a",
tertiaryDark: "#675445",
grayLight: "#1a1a1a",
gray: "#454444",
grayDark: "#808080",
success: "#84cc16",
error: "#ef4444",
warning: "#eab308",
info: "#06b6d4",
dark: "#ffffff",
light: "#000000",
};export const shadows: Shadows = {
xs: "0px 4px 4px 0px rgba(18, 18, 18, 0.04), 0px 1px 3px 0px rgba(39, 41, 45, 0.02)",
sm: "0px 4px 4px 0px rgba(18, 18, 18, 0.08), 0px 1px 3px 0px rgba(39, 41, 45, 0.04)",
md: "0px 8px 8px 0px rgba(18, 18, 18, 0.16), 0px 2px 3px 0px rgba(39, 41, 45, 0.06)",
lg: "0px 16px 24px 0px rgba(18, 18, 18, 0.20), 0px 2px 3px 0px rgba(39, 41, 45, 0.08)",
xl: "0px 24px 32px 0px rgba(18, 18, 18, 0.24), 0px 2px 3px 0px rgba(39, 41, 45, 0.12)",
};A dark counterpart, shadowsDark, is also exported and used by themeDark. It uses white shadows at the same offsets and opacities so elevation stays visible on dark surfaces:
export const shadowsDark: Shadows = {
xs: "0px 4px 4px 0px rgba(255, 255, 255, 0.04), 0px 1px 3px 0px rgba(255, 255, 255, 0.02)",
sm: "0px 4px 4px 0px rgba(255, 255, 255, 0.08), 0px 1px 3px 0px rgba(255, 255, 255, 0.04)",
md: "0px 8px 8px 0px rgba(255, 255, 255, 0.16), 0px 2px 3px 0px rgba(255, 255, 255, 0.06)",
lg: "0px 16px 24px 0px rgba(255, 255, 255, 0.20), 0px 2px 3px 0px rgba(255, 255, 255, 0.08)",
xl: "0px 24px 32px 0px rgba(255, 255, 255, 0.24), 0px 2px 3px 0px rgba(255, 255, 255, 0.12)",
};export const fonts: Fonts = {
text: "Inter",
head: "Inter",
mono: "monospace",
};export const fontSizes: FontSizes = {
hero1: { xs: "72px", lg: "128px" },
hero2: { xs: "60px", lg: "96px" },
hero3: { xs: "36px", lg: "72px" },
h1: { xs: "40px", lg: "60px" },
h2: { xs: "30px", lg: "36px" },
h3: { xs: "28px", lg: "30px" },
h4: { xs: "26px", lg: "24px" },
h5: { xs: "18px", lg: "20px" },
h6: { xs: "16px", lg: "18px" },
text: { xs: "14px", lg: "16px" },
strong: { xs: "14px", lg: "16px" },
small: { xs: "12px", lg: "14px" },
blockquote: { xs: "16px", lg: "18px" },
code: { xs: "14px", lg: "16px" },
button: { xs: "16px", lg: "16px" },
buttonBig: { xs: "18px", lg: "18px" },
buttonSmall: { xs: "14px", lg: "14px" },
input: { xs: "16px", lg: "16px" },
inputBig: { xs: "18px", lg: "18px" },
inputSmall: { xs: "14px", lg: "14px" },
};export const lineHeights: LineHeights = {
hero1: { xs: "1.10", lg: "1.10" },
hero2: { xs: "1.10", lg: "1.10" },
hero3: { xs: "1.20", lg: "1.10" },
h1: { xs: "1.50", lg: "1.40" },
h2: { xs: "1.50", lg: "1.50" },
h3: { xs: "1.30", lg: "1.50" },
h4: { xs: "1.30", lg: "1.50" },
h5: { xs: "1.60", lg: "1.50" },
h6: { xs: "1.60", lg: "1.60" },
text: { xs: "1.70", lg: "1.70" },
strong: { xs: "1.70", lg: "1.70" },
small: { xs: "1.70", lg: "1.70" },
blockquote: { xs: "1.70", lg: "1.70" },
code: { xs: "1.70", lg: "1.70" },
button: { xs: "1.00", lg: "1.00" },
buttonBig: { xs: "1.00", lg: "1.00" },
buttonSmall: { xs: "1.00", lg: "1.00" },
input: { xs: "1.00", lg: "1.00" },
inputBig: { xs: "1.00", lg: "1.00" },
inputSmall: { xs: "1.00", lg: "1.00" },
};These sections, together with the isDark flag, make up the exported theme and themeDark objects:
export const theme: Theme = {
breakpoints,
spacing,
colors,
shadows,
fonts,
fontSizes,
lineHeights,
isDark: false,
};
export const themeDark: Theme = {
breakpoints,
spacing,
colors: colorsDark,
shadows: shadowsDark,
fonts,
fontSizes,
lineHeights,
isDark: true,
};Using Shadows
Every theme ships five shadow levels (xs, sm, md, lg, xl) under theme.shadows. Reference them in your styled components to add elevation. When you pass themeDark to CherryThemeProvider, the dark theme swaps in shadowsDark, so elevation adapts to light and dark mode automatically:
import styled from "styled-components";
const Card = styled.div`
background: ${({ theme }) => theme.colors.light};
border-radius: ${({ theme }) => theme.spacing.radius.lg};
box-shadow: ${({ theme }) => theme.shadows.md};
`;See the Shadows foundation page for the full list of values.
Extending the Theme
When extending the Cherry theme, adhere to established patterns. Cherry uses the following size patterns: xs, sm, md, lg, xl, xxl, and xxxl. These patterns define not only media queries but also various other sizes.
If you extend the theme, ensure that you add the necessary type definitions to maintain consistency. All theme section interfaces (Theme, Breakpoints, Spacing, Colors, Shadows, Fonts, FontSizes, LineHeights) are exported, so you can extend them in TypeScript.