ThiloDesign System
DV

Theme Toggle

thilo custom
next-themes

Switches between Light, Dark, and System theme. Persists in localStorage.

@/components/ui/theme-toggle

Live — click to switch

Opens a dropdown with Light / Dark / System options

The same toggle appears in the top-right corner of every page in the AppShell top bar.

Modes

ModeDescription
Light
Forces light theme regardless of OS setting. Adds no class to <html>.
Dark
Forces dark theme. Adds class="dark" to <html>.
System
Follows OS preference via prefers-color-scheme media query.

How tokens flip between themes

Every semantic token has two values in globals.css — one for :root (light) and one for .dark. Switching theme swaps all values instantly.

TokenLight valueDark valueTailwind class
--backgroundoklch(1 0 0)oklch(0.145 0 0)bg-background
--foregroundoklch(0.145 0 0)oklch(0.985 0 0)text-foreground
--cardoklch(1 0 0)oklch(0.205 0 0)bg-card
--mutedoklch(0.97 0 0)oklch(0.269 0 0)bg-muted
--borderoklch(0.922 0 0)oklch(0.269 0 0)border-border
--status-openoklch(0.5 0.2 250)oklch(0.7 0.2 250)text-status-open-fg

In context — placement in the top bar

thilo
TicketsPartnersReports
DA
Page content area

How it works

LayerWhat it does
next-themes ThemeProviderWraps the app in layout.tsx. Reads/writes theme to localStorage. Sets class="dark" on <html>.
globals.css :rootDefines all semantic tokens as light values (oklch colors).
globals.css .darkOverrides every token to dark values. No component code changes.
ThemeToggle componentUses useTheme() hook from next-themes. Opens a DropdownMenu with 3 options.
All shadcn componentsAlready respond to .dark class automatically via CSS custom properties.

This is why using semantic tokens (bg-card, text-foreground) everywhere is mandatory — any hardcoded primitive (bg-zinc-950) will not respond to theme switching.

On this page