Theming
Using CSS variables and the css() mixin to theme components.
How it works
Components read colors and radii from CSS variables defined in app/ui/globals.css — exactly the shadcn/ui tokens. Change a variable and every component follows.
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--radius: 0.625rem;
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
}Dark mode
Add the dark class to <html> to switch themes. Component styles target .dark &, the same as Tailwind’s dark: variant.
Convention
Every color comes as a pair: --x for the background and --x-foreground for the text on it.
| Variable | Used for |
|---|---|
--background / --foreground | Page background and default text |
--card / --card-foreground | Cards |
--popover / --popover-foreground | Popovers, menus, selects |
--primary / --primary-foreground | Primary buttons, active states |
--secondary / --secondary-foreground | Secondary buttons |
--muted / --muted-foreground | Muted backgrounds and descriptions |
--accent / --accent-foreground | Hover and highlighted items |
--destructive | Destructive actions and errors |
--border, --input, --ring | Borders, inputs, focus rings |
--sidebar-* | The sidebar component |
--chart-1 … --chart-5 | Charts |
Radius
--radius drives every corner: calc(var(--radius) - 4px) for small elements, calc(var(--radius) - 2px) for controls, var(--radius) for surfaces and calc(var(--radius) + 4px) for cards.
Customizing components
Every component accepts mix, applied after its own styles. Each css() call is its own cascade layer, ordered by first use, so your mix always wins over the component — no !important, no class merging.
<Button variant="outline" mix={css({ borderRadius: '9999px' })}>
Rounded
</Button>