# ThemeProvider

Provides the theme context to all child components, and automatically generates CSS Variables for dynamic theming.

## Import

```tsx
import { ThemeProvider } from '@coinbase/cds-web'
```

## Examples

import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';
import { createThemeCssVars } from '@coinbase/cds-web/core/createThemeCssVars';
import { JSONCodeBlock } from '@site/src/components/page/JSONCodeBlock';

### ThemeProvider component

The ThemeProvider provides the theme context to all child components, and automatically generates CSS Variables for dynamic theming.

You must pass the `theme` prop to configure the theme, and the `activeColorScheme` prop to set light or dark mode.

```tsx
import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';

const App = () => (
  <ThemeProvider theme={defaultTheme} activeColorScheme="light">
    {/* Your app components */}
  </ThemeProvider>
);
```

:::tip
Changing the `activeColorScheme` automatically updates the values returned from the `useTheme` hook and from CSS Variables.
:::

### `useTheme` hook

The `useTheme` hook provides access to the current `theme` and `activeColorScheme`.

The `color` and `spectrum` objects automatically change based on the `activeColorScheme`.

[See the `useTheme` docs here &rarr;](/hooks/useTheme)

```jsx
const theme = useTheme();
theme.activeColorScheme; // "light" or "dark"
theme.spectrum; // Resolves to lightSpectrum or darkSpectrum, depends on activeColorScheme
theme.color; // Resolves to lightColor or darkColor, depends on activeColorScheme
theme.color.bgPrimary; // "rgb(0,82,255)" or "rgb(87,139,250)", depends on activeColorScheme
theme.space[2]; // 16
theme.borderRadius[200]; // 8
theme.fontSize.display3; // "2.5rem"
```

:::tip
For best performance, prefer to use CSS Variables instead of the `useTheme` hook whenever possible.
:::

### ThemeProvider CSS Variables

CSS Variables are created for every value in the theme.

For best performance, prefer to use CSS Variables instead of the `useTheme` hook whenever possible.

```jsx
const theme = useTheme();
theme.color.bgPrimary; // --color-bgPrimary
theme.lightColor.bgPrimary; // --lightColor-bgPrimary
theme.darkColor.bgPrimary; // --darkColor-bgPrimary
theme.spectrum.blue10; // --blue10
theme.lightSpectrum.blue10; // --light-blue10
theme.darkSpectrum.blue10; // --dark-blue10
theme.space[2]; // --space-2
theme.space[0.25]; // --space-0_25
theme.borderRadius[400]; // --borderRadius-400
theme.fontSize.body; // --fontSize-body
```

You can see all the CSS Variables for the `defaultTheme` below.

<JSONCodeBlock json={createThemeCssVars(defaultTheme)} />

### ThemeProvider classnames

The ThemeProvider renders with CSS classnames based on the `activeColorScheme` and the theme's `id`.

This allows you to style components based on the `activeColorScheme` or the theme's `id`.

```jsx
// Renders with a .cds-default class and a .light class
<ThemeProvider theme={defaultTheme} activeColorScheme="light" />
```

### Nested themes

ThemeProviders can be nested to create theme overrides for specific sections.

```jsx
<ThemeProvider theme={defaultTheme} activeColorScheme="light">
  {/* Default theme in light color scheme */}

  <ThemeProvider theme={customTheme} activeColorScheme="dark">
    {/* Custom theme in dark color scheme */}
  </ThemeProvider>
</ThemeProvider>
```

When nesting, you may want to override specific color values from the current theme. Overrides must be conditionally applied because we don't enforce that a theme has both light and dark colors defined.

```jsx
// Override parts of the parent theme
const theme = useTheme();
const customTheme = {
  ...theme,
  ...(theme.lightColor &&
    theme.lightSpectrum && {
      lightColor: {
        ...theme.lightColor,
        bg: `rgb(${theme.lightSpectrum.orange50})`,
        bgPrimary: `rgb(${theme.lightSpectrum.red20})`,
        bgSecondary: `rgb(${theme.lightSpectrum.blue50})`,
      },
    }),
  ...(theme.darkColor &&
    theme.darkSpectrum && {
      darkColor: {
        ...theme.darkColor,
        bg: `rgb(${theme.darkSpectrum.orange50})`,
        bgPrimary: `rgb(${theme.darkSpectrum.red20})`,
        bgSecondary: `rgb(${theme.darkSpectrum.blue50})`,
      },
    }),
} as const satisfies Theme;
```

### Theme inheritence

Nested ThemeProviders do not automatically inherit the theme from their parent provider. You can manually inherit the theme with the `useTheme` hook.

```jsx
const Example = () => {
  // Pass the parent theme down to another ThemeProvider
  const theme = useTheme();
  return (
    <ThemeProvider theme={theme} activeColorScheme={theme.activeColorScheme}>
      {children}
    </ThemeProvider>
  );
};
```

### InvertedThemeProvider component

The InvertedThemeProvider automatically inherits from its parent theme and flips the `activeColorScheme` to the opposite value.

```jsx live
<ThemeProvider theme={defaultTheme} activeColorScheme="light">
  {/* Default theme in light color scheme */}
  <Box background="bg" padding={2} borderRadius={400}>
    <Button>Hello world!</Button>
  </Box>
  <InvertedThemeProvider>
    {/* Default theme in inverse (dark) color scheme */}
    <Box background="bg" padding={2} borderRadius={400}>
      <Button>Hello world!</Button>
    </Box>
  </InvertedThemeProvider>
</ThemeProvider>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `activeColorScheme` | `light \| dark` | Yes | `-` | - |
| `theme` | `ThemeConfig` | Yes | `-` | - |
| `className` | `string` | No | `-` | - |
| `display` | `grid \| ruby \| table \| string & {} \| -moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none \| block \| inline \| inline-block \| flex \| inline-flex \| inline-grid \| contents \| flow-root \| list-item \| run-in \| -ms-flexbox \| -ms-grid \| -webkit-flex \| flow \| ruby-base \| ruby-base-container \| ruby-text \| ruby-text-container \| table-caption \| table-cell \| table-column \| table-column-group \| table-footer-group \| table-header-group \| table-row \| table-row-group \| -ms-inline-flexbox \| -ms-inline-grid \| -webkit-inline-flex \| inline-list-item \| inline-table` | No | `-` | - |
| `motionFeatures` | `FeatureBundle \| LazyFeatureBundle` | No | `-` | - |
| `style` | `CSSProperties` | No | `-` | - |


