Theming

Semantic color tokens, shape, dark mode and presets, and how to bring your own brand.

Color tokens

Components never use raw colors. They use shadcn's semantic tokens through Tailwind classes like bg-primary or text-muted-foreground. Change a token and every component follows, in light and dark mode. Values shown are the default theme; switch between light and dark to compare.

Show:
TokenValueUse it for
--background#ffffffThe page behind everything.
--foreground#0a0a0aMain text and icons.
--card#ffffffCards and panels on the page.
--popover#ffffffMenus, popovers and dialogs that float.
--primary#171717Main buttons and selected states. Your brand color.
--secondary#f5f5f5Secondary buttons and soft badges.
--muted#f5f5f5Quiet fills. Its foreground is for hints and descriptions.
--accent#f5f5f5Hover and focus fills in menus and lists.
--destructive#e7000bDelete actions and errors.
--border#e5e5e5One pixel separators and card edges.
--input#e5e5e5Borders of inputs and switches.
--ring#171717The focus outline.

πŸ’‘ Fills like --primary or --card each have a -foreground partner for the text on top, such as --primary-foreground. Change both together to keep text readable.

Shape and type

TokenUse it for
--radiusThe base corner radius (0.625rem by default). Tailwind's rounded-sm to rounded-xl are derived from it.
--shadow-xs … --shadow-lgShadows for cards and floating layers. Presets switch them between soft, hard and none.
font-familySet on body. Each preset suggests a stack: sans, rounded, serif or mono.

Dark mode

Dark values live in a .dark block and are tuned separately, not inverted. Add the dark class to <html> to switch. With Next.js, next-themes does it for you, follows the system setting and avoids a flash of the wrong theme:

1import { ThemeProvider } from "next-themes";
2
3export default function RootLayout({ children }: { children: React.ReactNode }) {
4 return (
5 <html lang="en" suppressHydrationWarning>
6 <body>
7 <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
8 {children}
9 </ThemeProvider>
10 </body>
11 </html>
12 );
13}

Presets

Start from one of 9 ready-made themes. Open one to see it on real blocks, then copy its CSS.

Want something else? The theme generator lets you adjust colors, radius, font and shadows, then copy the result.

Your own brand

Paste a theme into globals.css, replacing the :root and .dark blocks that shadcn init created. To change only a few things, override just those tokens and keep the rest. Check contrast, and set the dark values separately:

1:root {
2 --primary: oklch(0.55 0.15 180);
3 --primary-foreground: oklch(0.99 0 0);
4 --ring: oklch(0.55 0.15 180);
5 --radius: 0.75rem;
6}
7
8.dark {
9 --primary: oklch(0.75 0.13 180);
10 --primary-foreground: oklch(0.2 0.03 180);
11 --ring: oklch(0.75 0.13 180);
12}

The full default theme, if you want to start from every token:

1/* Default Β· generated by nextui */
2:root {
3 --radius: 0.625rem;
4 --background: oklch(1 0 0);
5 --foreground: oklch(0.145 0 0);
6 --card: oklch(1 0 0);
7 --card-foreground: oklch(0.145 0 0);
8 --popover: oklch(1 0 0);
9 --popover-foreground: oklch(0.145 0 0);
10 --primary: oklch(0.205 0 0);
11 --primary-foreground: oklch(0.985 0 0);
12 --secondary: oklch(0.97 0 0);
13 --secondary-foreground: oklch(0.205 0 0);
14 --muted: oklch(0.97 0 0);
15 --muted-foreground: oklch(0.556 0 0);
16 --accent: oklch(0.97 0 0);
17 --accent-foreground: oklch(0.205 0 0);
18 --destructive: oklch(0.583 0.239 28.5);
19 --border: oklch(0.922 0 0);
20 --input: oklch(0.922 0 0);
21 --ring: oklch(0.205 0 0);
22}
23
24.dark {
25 --background: oklch(0.145 0 0);
26 --foreground: oklch(0.985 0 0);
27 --card: oklch(0.205 0 0);
28 --card-foreground: oklch(0.985 0 0);
29 --popover: oklch(0.205 0 0);
30 --popover-foreground: oklch(0.985 0 0);
31 --primary: oklch(0.922 0 0);
32 --primary-foreground: oklch(0.205 0 0);
33 --secondary: oklch(0.269 0 0);
34 --secondary-foreground: oklch(0.985 0 0);
35 --muted: oklch(0.269 0 0);
36 --muted-foreground: oklch(0.709 0 0);
37 --accent: oklch(0.269 0 0);
38 --accent-foreground: oklch(0.985 0 0);
39 --destructive: oklch(0.702 0.189 22.2);
40 --border: oklch(0.301 0 0);
41 --input: oklch(0.348 0 0);
42 --ring: oklch(0.922 0 0);
43}
44
45/* font-family: ui-sans-serif, system-ui, sans-serif */