# Theme

> The Cherry theme object defines media queries, spacing, colors, font sizes, line heights, and shadows.

Source: https://cherry.al/code/theme

> For the complete documentation index, see [llms.txt](https://cherry.al/llms.txt).

# 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](/figma) documentation for details.

Wrap your entire application with `CherryThemeProvider` to ensure all components have access to the theme:

```tsx
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](/code/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:

<Accordion title="1. Breakpoints">

```tsx
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:

```tsx
import styled from "styled-components";
import { mq } from "cherry-styled-components";

const Wrapper = styled.div`
  padding: 20px;

  ${mq("lg")} {
    padding: 40px;
  }
`;
```

</Accordion>

<Accordion title="2. Spacing">

```tsx
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" },
};
```

</Accordion>

<Accordion title="3. Colors">

```tsx
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:

```tsx
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",
};
```

</Accordion>

<Accordion title="4. Shadows">

```tsx
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:

```tsx
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)",
};
```

</Accordion>

<Accordion title="5. Fonts">

```tsx
export const fonts: Fonts = {
  text: "Inter",
  head: "Inter",
  mono: "monospace",
};
```

</Accordion>

<Accordion title="6. Font Sizes">

```tsx
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" },
};
```

</Accordion>

<Accordion title="7. Line Heights">

```tsx
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" },
};
```

</Accordion>

These sections, together with the `isDark` flag, make up the exported `theme` and `themeDark` objects:

```tsx
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:

```tsx
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};
`;
```

<iframe className="light-only" src="https://demo.cherry.al/preview/shadows?theme=light" title="Shadow elevations" loading="lazy" style={{ width: "100%", height: "500px", border: "1px solid var(--color-grayLight)", borderRadius: "12px" }} />
<iframe className="dark-only" src="https://demo.cherry.al/preview/shadows?theme=dark" title="Shadow elevations" loading="lazy" style={{ width: "100%", height: "500px", border: "1px solid var(--color-grayLight)", borderRadius: "12px" }} />

See the [Shadows](/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.

<Button href="https://github.com/cherry-design-system/styled-components/blob/main/src/lib/utils/theme.ts" icon="code" iconPosition="left">
  View Source
</Button>
