Xzero UI
Pro library

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.

neutralvioletbluegreenamberorangecoralrose
index.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 "../components/xzero/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;}