Vesyl UI

Color

Color in ui-next is two tiers. Primitives are the raw palette — a fixed ramp of values you can reach for directly. Semantic roles sit on top: tokens named for a job (a fill, a border, body text) that point at different primitive steps in light versus dark. You style against the role and the palette handles the mode for you.

Everything is authored in OKLCH (oklch(lightness chroma hue)) in a single file — web/ui-next/src/theme/colors.css. Every swatch on this page links into colorpicker.dev — its hash carries the exact L, C, H, so you can open a value, nudge it, and copy it straight back. Dark mode is the .dark class: every semantic token is declared once under :root and again under .dark, and Tailwind v4 re-exports them as utilities (bg-primary, text-accent-foreground, …) via @theme inline.

The accent ramp

The accent is VESYL’s brand blue expanded into a full 25950 ramp. Lightness walks a smooth perceptual curve; chroma peaks through the mid steps and tapers at the ends so the lightest and darkest steps stay clean rather than washed-out or neon. Each step is available as a utility — bg-accent-500, text-accent-700, border-accent-200, and so on.

25
oklch(0.985 0.005 233)
50
oklch(0.97 0.012 233)
100
oklch(0.937 0.026 233)
200
oklch(0.89 0.048 233)
300
oklch(0.822 0.078 233)
400
oklch(0.738 0.108 233)
500
oklch(0.652 0.128 233)
600
oklch(0.574 0.132 233)
700
oklch(0.498 0.118 233)
800
oklch(0.428 0.098 233)
900
oklch(0.368 0.078 233)
950
oklch(0.288 0.058 233)

The ramp is fixed — identical in light and dark. That makes it the right tool when you decide the value for a context: chart series, gradients, illustrations, a decorative tint. It is the wrong tool for anything that must adapt between modes, because accent-50 as a surface blinds you on a dark canvas and accent-950 as text vanishes on it. For mode-adaptive UI, reach for a role.

Semantic accent roles

Each role names a job and resolves to a different ramp step per mode — so the same class reads correctly in both. The panels below are pinned to light and dark side by side; toggle the docs theme to confirm the live classes track it.

Light
Accent
Hover
Subtle
Border
Accent link
Dark
Accent
Hover
Subtle
Border
Accent link
RoleUse forStep · light / dark
accent / accent-foregroundSolid fill + its text — the primary accent button600 · 600
accent-emphasisHover / active of the solid fill700 · 500
accent-subtle / -foregroundTinted surface + its text — badges, callouts50/700 · 950/200
accent-mutedBorders, dividers, faint outlines200 · 800
accent-textAccent-colored text & links on the page700 · 300

Composed together, the roles cover the common accent surfaces without any per-mode branching at the call site:

New
12 new orders streamed in.
View details

Step or role?

  • Reach for a role (bg-accent, bg-accent-subtle, text-accent-text, border-accent-muted) for anything users interact with or read. It is the default, and it stays correct when the theme flips.
  • Reach for a raw step (bg-accent-500) only when the value is yours to own per mode — data visualization, decoration, one-off art direction. If you find yourself writing dark:bg-accent-300 to fix a raw step, that is the signal a role already exists for what you are doing.

The semantic system

The accent is one family inside a larger neutral-and-semantic system. These tokens predate the accent ramp and drive nearly all chrome — surfaces, text, borders, status. Surface tokens are paired with a -foreground for text that sits on them; the swatches show that pairing as “Aa”.

Light
Aa
background
Aa
card
Aa
popover
Aa
primary
Aa
secondary
Aa
muted
Aa
subtle
Aa
emphasized
Aa
highlight
Aa
destructive
border
ring
Dark
Aa
background
Aa
card
Aa
popover
Aa
primary
Aa
secondary
Aa
muted
Aa
subtle
Aa
emphasized
Aa
highlight
Aa
destructive
border
ring

A few notes on the set:

  • background / card / popover are the surface stack; primary and secondary are the high- and low-emphasis solid fills.
  • muted, subtle, and emphasized are graded neutral surfaces for receding or lifting content.
  • highlight is the interactive hover/focus/selected surface used by menus, selects, and list items. (It was previously named accent — that name now belongs to the brand accent above.)
  • border, border-strong, input, and ring handle outlines and focus rings.

Chart colors

chart-1 through chart-5 are a dedicated categorical sequence for data visualization. They are intentionally fixed across modes so a series keeps its identity when the theme changes.

chart-1
chart-2
chart-3
chart-4
chart-5

Working in OKLCH

OKLCH makes the dark-mode mapping tractable: lightness is perceptual, so flipping a token between modes is mostly a matter of moving along the lightness axis while holding hue and chroma. colorpicker.dev is a solid OKLCH picker for dialing this in — and since every swatch above deep-links to it, you can start from an existing step rather than a blank canvas. When adding or adjusting a token, edit only web/ui-next/src/theme/colors.css — declare the value under both :root and .dark, then add the matching --color-* line to the @theme inline block so the Tailwind utility exists.