Navigation: [/sitemap.md](/sitemap.md)

---
type: doc
title: Dark mode
description: Add a class-based dark mode with the theme toggle.
---

Fulldev UI uses class-based dark mode, like shadcn/ui. When `<html>` has the
`dark` class, every component switches to the `.dark` token values from
`src/styles/global.css`. The `dark:` Tailwind variant is wired to that class:

```css
@custom-variant dark (&:where(.dark, .dark *));
```

## Setup

Install the theme toggle:

```bash
npx shadcn@latest add @fulldev/theme-toggle
```

Render `ThemeProvider` in the document head. It runs an inline script before
paint that reads the saved preference (or the system preference) and sets the
`dark` class, so there is no flash of the wrong theme:

```astro title="src/layouts/layout.astro"
---
import { ThemeProvider, ThemeToggle } from "@/components/ui/theme-toggle"
---

<html lang="en">
  <head>
    <ThemeProvider />
  </head>
  <body>
    <ThemeToggle />
    <slot />
  </body>
</html>
```

`ThemeToggle` switches between light and dark and stores the choice in
`localStorage`.

## Dark sections on a light page

Add the `dark` class to any element to force its subtree into dark tokens.
Several blocks use this for contrast sections:

```astro
<Section class="dark bg-background text-foreground">...</Section>
```

## Without a toggle

If the site should follow the system preference only, skip `ThemeToggle` and
keep `ThemeProvider`. It falls back to `prefers-color-scheme` when nothing is
stored.
