> For AI agents: the complete Sanity documentation index is available at [https://www.sanity.io/docs/llms.txt](https://www.sanity.io/docs/llms.txt).

# Match the Dashboard's color scheme

Follow the Dashboard's light or dark mode in your app, panels, and tiles with Sanity UI v4 or any other styling library.

Users switch the Dashboard between light and dark mode, or have it follow their operating system, from the account menu. Your app renders inside the Dashboard's page, so match its color scheme to fit in. Read the scheme with `useTopic('preferences.color-scheme')` from `@sanity/sdk-react/dashboard`.

## Requirements

- `@sanity/sdk-react` 3.9.0 or later.
- An app configured with `defineApplication`, running under `sanity dev` or deployed with it.

## Read the color scheme

`preferences.color-scheme` is `'light'` or `'dark'`. When the user chooses System, the Dashboard resolves it from the operating system, so your app always receives one of the two. The hook suspends until the Dashboard sends the first value, and re-renders your component whenever the user changes the setting.

## Apply it to Sanity UI v4

This example uses `@sanity/ui` v4, which the Sanity UI template installs. Pass the scheme to the `scheme` prop of `ThemeProvider`. `useTopic` needs an App SDK instance, so render `ThemeProvider` inside `SanityApp`:

**src/App.tsx**

```tsx
import '@sanity/ui/styles.css'
import {type SanityConfig} from '@sanity/sdk'
import {SanityApp} from '@sanity/sdk-react'
import {useTopic} from '@sanity/sdk-react/dashboard'
import {ThemeProvider} from '@sanity/ui'
import {buildTheme} from '@sanity/ui/theme'
import type {ReactNode} from 'react'
import {ExampleComponent} from './ExampleComponent'

const theme = buildTheme()

const config: SanityConfig[] = [
  {
    projectId: 'your-project-id',
    dataset: 'production',
  },
]

function DashboardTheme({children}: {children: ReactNode}) {
  const scheme = useTopic('preferences.color-scheme')
  return (
    <ThemeProvider theme={theme} scheme={scheme}>
      {children}
    </ThemeProvider>
  )
}

export default function App() {
  return (
    <SanityApp config={config} fallback={null}>
      <DashboardTheme>
        <ExampleComponent />
      </DashboardTheme>
    </SanityApp>
  )
}
```

`SanityApp` renders its `fallback` before `ThemeProvider` mounts, so don't use `@sanity/ui` components in the fallback.

Apps created from the Sanity UI template wrap `SanityApp` in a `ThemeProvider` in `src/SanityUI.tsx`. Move the `ThemeProvider` inside `SanityApp` so it can read the scheme.

## Apply it to other styling libraries

The same approach works with any styling library: read the scheme from the Dashboard, then pass it to whatever your library uses to switch modes. Follow these rules:

- Read the scheme with `useTopic`, not from `prefers-color-scheme` or the library's own detection. The user's Dashboard setting can differ from their operating system.
- Pass the scheme to the library's mode setting, such as a theme provider's mode or color scheme option.
- Scope it to your app's root element. Your app renders into the Dashboard's page rather than its own document, so don't let the library change `document.documentElement`, `document.body`, or global styles. Turn off any global CSS reset the library applies, or use its scoped version.
- Pass the value straight through instead of copying it into state. `useTopic` re-renders your component whenever the user changes the setting.

### Plain CSS

Put the scheme on a root element as a data attribute, and define your colors for each scheme:

**src/SchemeRoot.tsx**

```tsx
import {useTopic} from '@sanity/sdk-react/dashboard'
import type {ReactNode} from 'react'

export function SchemeRoot({children}: {children: ReactNode}) {
  const scheme = useTopic('preferences.color-scheme')
  return (
    <div className="app-root" data-scheme={scheme}>
      {children}
    </div>
  )
}
```

**src/app.css**

```css
.app-root {
  color-scheme: light;
  --app-background: #ffffff;
  --app-text: #101112;
  background: var(--app-background);
  color: var(--app-text);
}

.app-root[data-scheme='dark'] {
  color-scheme: dark;
  --app-background: #101112;
  --app-text: #ffffff;
}
```

Render `SchemeRoot` inside `SanityApp`. The `color-scheme` property also switches browser-drawn elements such as scrollbars and form controls.

### Tailwind CSS v4

Point Tailwind's `dark` variant at the same data attribute, then use `dark:` utilities inside `SchemeRoot`:

**src/app.css**

```css
@import "tailwindcss";
@custom-variant dark (&:where([data-scheme=dark], [data-scheme=dark] *));
```

## Match the color scheme in panels and tiles

Panel components, panel titles, and tiles each render in their own island, so add the theme to the `Providers` component that wraps them:

**src/Providers.tsx**

```tsx
import '@sanity/ui/styles.css'
import {SanityApp} from '@sanity/sdk-react'
import {useTopic} from '@sanity/sdk-react/dashboard'
import {ThemeProvider} from '@sanity/ui'
import {buildTheme} from '@sanity/ui/theme'
import type {ReactNode} from 'react'

const theme = buildTheme()

function DashboardTheme({children}: {children: ReactNode}) {
  const scheme = useTopic('preferences.color-scheme')
  return (
    <ThemeProvider theme={theme} scheme={scheme}>
      {children}
    </ThemeProvider>
  )
}

export function Providers({children}: {children: ReactNode}) {
  return (
    <SanityApp fallback={null}>
      <DashboardTheme>{children}</DashboardTheme>
    </SanityApp>
  )
}
```

## Next steps

[Read Dashboard state](https://www.sanity.io/docs/dashboard-beta/read-dashboard-state)
Read the organization, user, and other Dashboard state.

[Render a panel](https://www.sanity.io/docs/dashboard-beta/render-a-panel)
Open a view from the dock.

[Render a tile on the home page](https://www.sanity.io/docs/dashboard-beta/render-a-tile)
Show a view on the Dashboard home page.

