Customization

Theming

Every design decision lives in one stylesheet, @viliha/vui-react/theme.css, as a CSS variable. Change the tokens and the whole system follows.

Token groups

  • Surfaces & text: --background, --foreground, --card, --popover, --muted, --accent.
  • Actions: --primary, --destructive, and the brand --button-primary / --button-primary-hover / --button-shadow.
  • Lines & focus: --border, --input, --ring.
  • Sidebar, charts, radius, selection: --sidebar-*, --chart-1..5, --radius, --selection.

Color system

These are the semantic colors you reach for most. Every component reads them, so changing a single token restyles the whole system. Each pairs with a matching -foreground for the text that sits on top.

ColorTokenValue
Brand--brand#0058EE
Primary (action)--button-primaryvar(--brand)
Primary hover--button-primary-hovercolor-mix(in oklab, var(--brand) 84%, black)
Foreground--foreground#101112
Primary (neutral)--primaryoklch(0.205 0 0)
Secondary--secondaryoklch(0.97 0 0)
Hover surface--accentoklch(0.97 0 0)
Muted--mutedoklch(0.97 0 0)
Destructive--destructiveoklch(0.577 0.245 27)
Success--success#039855
Warning--warning#dc6803
Info--info#0086c9
Border--borderoklch(0.922 0 0)
Ring--ringoklch(0.708 0 0)
Selection--selectionvar(--brand)

💡 Four state colours, and all four are yours

--destructive, --success, --warning and --info are the whole state family, in light and dark. Nothing in the components reaches past them to a fixed palette colour, so overriding these four moves every badge, alert, status dot and delta arrow in the product at once. There is a test that goes red if a palette class comes back.

Primary: neutral vs. action

shadcn's --primary is the neutral, near-black solid the default button uses. The brand action color is a separate token, --button-primary (#0058EE), paired with --button-primary-hover for its hover state. It drives <Button variant="primary">, checkboxes, and active states, while hover surfaces (rows, items, ghost buttons) fall back to --accent.

Default tokens

theme.css (excerpt)
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.177 0 0);   /* #101112 */
  --primary: oklch(0.205 0 0);
  --radius: 0.625rem;
  --brand: #0058ee;                 /* the one brand colour */
  --selection: var(--brand);
  --button-primary: var(--brand);   /* brand primary button */
  /* …neutral palette, chart + sidebar tokens… */
}

How do I rebrand the theme?

Override tokens after importing the theme:

app/globals.css
@import "tailwindcss";
@import "@viliha/vui-react/theme.css";

:root {
  --primary: oklch(0.55 0.2 260);  /* your brand */
  --radius: 0.5rem;
}

How does dark mode work?

The tokens ship with a .dark block. Add the dark class to <html> to switch, and wire that class to a theme toggle or the OS preference.

<html class="dark">

Typography

The baseline is Inter at 14px medium in #101112. To match the demo, supply the --font-inter and --font-jetbrains-mono CSS variables, for example through next/font.