Skip to main content

Theming

Override one CSS variable. The entire library responds.

How Tokens Work

VhyxUI uses a two-layer token system. The primitive layer holds raw values — exact hex colors, pixel counts. The semantic layer defines what those values mean: background, accent, border, text. Components always reference semantic tokens, never primitives directly.

This separation is what makes theming instantaneous. When you override --vhyx-color-accent, every component that uses accent — buttons, focus rings, badges, active states — updates with no rebuild, no config change, no JavaScript.

/* Primitive — raw color values */
--vhyx-primitive-indigo-500: #6366f1;

/* Semantic — what components use */
--vhyx-color-accent: var(--vhyx-primitive-indigo-500);

/* Component uses semantic token — override here to theme */
background: var(--vhyx-color-accent);
The ruleOverride semantic tokens to theme. Never touch primitives.

Override Tokens

Example 1 — Brand color

Replace the default indigo accent with a rose palette. Five tokens cover the full accent family — default, hover, active, and the two subtle fills used in badges and backgrounds.

:root {
  --vhyx-color-accent:        #e11d48;
  --vhyx-color-accent-hover:  #be123c;
  --vhyx-color-accent-active: #9f1239;
  --vhyx-color-accent-subtle: #fff1f2;
  --vhyx-color-accent-muted:  #ffe4e6;
}

Example 2 — Sharp corners

Collapse every radius token to zero for a strict, editorial aesthetic. Keep --vhyx-radius-full intact so pill shapes like badge dots remain circular.

:root {
  --vhyx-radius-xs:   0;
  --vhyx-radius-sm:   0;
  --vhyx-radius-md:   0;
  --vhyx-radius-lg:   0;
  --vhyx-radius-xl:   0;
  --vhyx-radius-2xl:  0;
  --vhyx-radius-3xl:  0;
  --vhyx-radius-full: 9999px; /* keep pill shapes */
}

Example 3 — Custom font

Point the sans and mono font stacks at your typefaces. Ensure the fonts are loaded before applying — add them via next/font or a stylesheet import.

:root {
  --vhyx-font-sans: 'Inter', system-ui, sans-serif;
  --vhyx-font-mono: 'Fira Code', ui-monospace, monospace;
}

Live demo — rose theme applied

Live

Dark Mode

VhyxUI ships a complete dark theme. It activates when the data-theme="dark" attribute is set on any ancestor element — typically the html element.

HTML attribute approach

<!-- Set on the html element -->
<html data-theme="dark">

<!-- Or toggle via JavaScript -->
document.documentElement.setAttribute('data-theme', 'dark');
document.documentElement.setAttribute('data-theme', 'light');

With next-themes (recommended)

terminal
npm install next-themes
app/providers.tsx
import { ThemeProvider } from 'next-themes';
import { VhyxUIProvider } from '@vhyxui/react';

export function Providers({ children }) {
  return (
    <ThemeProvider
      attribute="data-theme"
      defaultTheme="system"
      enableSystem
    >
      <VhyxUIProvider>
        {children}
      </VhyxUIProvider>
    </ThemeProvider>
  );
}
Already workingVhyxUI docs and playground use next-themes with the data-theme attribute. You can see it working right now with the toggle in the header.

A complete custom theme

These 15 token overrides completely transform VhyxUI. Override them in your globals.css inside :root.

:root {
  /* Accent — rose */
  --vhyx-color-accent:         #e11d48;
  --vhyx-color-accent-hover:   #be123c;
  --vhyx-color-accent-active:  #9f1239;
  --vhyx-color-accent-subtle:  #fff1f2;
  --vhyx-color-accent-muted:   #ffe4e6;

  /* Border radii — softer */
  --vhyx-radius-sm:  6px;
  --vhyx-radius-md:  10px;
  --vhyx-radius-lg:  14px;
  --vhyx-radius-xl:  18px;

  /* Typography */
  --vhyx-font-sans: 'Inter', system-ui, sans-serif;

  /* Surfaces — warm white */
  --vhyx-color-surface:        #fffbf9;
  --vhyx-color-surface-raised: #ffffff;
  --vhyx-color-bg:             #fdf8f6;
  --vhyx-color-bg-subtle:      #faf0ec;
  --vhyx-color-border:         #f2d8d0;
}
That's itNo build step. No configuration file. Just CSS.