Theming
Semantic color tokens, dark mode, accents, and how to bring your own brand.
Color tokens
Components only use semantic roles, never raw colors. Change a role and every component follows, in both themes. The swatches below show the current values.
TokenUse it for
--backgroundThe page behind everything.--surfaceCards, inputs, and panels on the page.--surface-raisedMenus, popovers, and dialogs that float.--surface-mutedQuiet fills: hover states, wells, code.--foregroundPrimary text and icons.--text-secondarySupporting text and descriptions.--text-mutedHints, placeholders, and metadata.--borderDefault one pixel separators.--border-subtleDividers inside a surface.--border-strongHovered or pressed edges.--accentSelected navigation, progress, and helpful context.--successCompleted and healthy states, with a label.--warningNeeds attention soon, with a label.--dangerDestructive actions and errors, with a label.Shape and type
TokenUse it for
--radius-controlInputs and buttons (18px).--radius-panelMenus and nested panels (26px).--radius-surfaceCards and large surfaces (34px).--font-displayGeist, for headings at 30px and above.--font-bodyInter, for everything else.--shadow-floatingOnly for layers that float above content.Dark mode
Set data-theme="dark" on <html>. Dark values are tuned separately rather than inverted. To avoid a flash of the wrong theme, set the attribute before the page paints:
app/layout.tsx
const themeScript = `try { const saved = localStorage.getItem("theme"); const dark = saved ? saved === "dark" : matchMedia("(prefers-color-scheme: dark)").matches; document.documentElement.dataset.theme = dark ? "dark" : "light";} catch {}`; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" suppressHydrationWarning> <head><script dangerouslySetInnerHTML={{ __html: themeScript }} /></head> <body>{children}</body> </html> );}Accents
Set data-accent on <html> to one of eight built-in accents. The accent marks selection and progress; most surfaces stay neutral.
neutralvioletbluegreenamberorangecoralroseindex.html
<html data-theme="light" data-accent="violet">Your own brand
Override roles after importing the foundation. Keep contrast in mind and set dark values separately.
app/globals.css
@import "../registry/foundation.css"; :root { --accent: #0f766e; --accent-strong: #0b5a54; --accent-subtle: rgb(15 118 110 / .12); --radius-control: 12px;} :root[data-theme="dark"] { --accent: #2dd4bf; --accent-strong: #5eead4;}