Theming

Semantic CSS variables, a dark token set and runtime accent generation. Change one color and the whole system re-tones.

Try it

Accent

Pick a preset or a custom color. The change applies instantly across the site.

default

Applies the .dark token set.

PrimarySolidSuccessWarningDanger

Semantic tokens

Components only read semantic tokens. Override them on the element that carries data-ui="kit" (or on any descendant) to re-theme a subtree.

Surfaces
--background, --card, --surface, --field, --popover, --muted
Actions
--primary, --primary-foreground, --primary-hover, --primary-soft, --ring
Status
--destructive, --success, --warning, --info
Shape
--radius-control, --radius-field, --radius-card, --radius-overlay
Lighting
--light-top, --light-sheen, --light-bottom, --light-rim

The default light/dark values live in packages/ui-kit/src/styles/theme.css. Components never use app-specific variables or raw paints where a token exists.

Accent generation

generateAccentVars(color, mode) derives a full primary scale from one color: primary, foreground, hover, active, soft and ring. The docs site applies the result to <html> so portalled overlays inherit it.

accent.tsx
import { accentStyle } from "@nphuonha/ui-kit";
<div data-ui="kit" style={accentStyle("#0d9488", "light")}>
<App />
</div>
// Or generate the variables directly:
import { generateAccentVars } from "@nphuonha/ui-kit";
const vars = generateAccentVars("#0d9488", "dark");

Dark mode

Add .dark to the same element as data-ui="kit". Accent variables should be regenerated for the active mode:

theme.ts
const mode = isDark ? "dark" : "light";
const vars = generateAccentVars(accent, mode);
for (const [key, value] of Object.entries(vars)) {
document.documentElement.style.setProperty(key, value);
}

Surface lighting

Solid surfaces get their curve from a top-lit rim and a micro gradient. Use the utilities instead of hand-rolling borders and shadows:

surface-curved

Cards, dialogs, popovers and primary buttons.

surface-curved-soft

Secondary buttons, tabs, alerts, badges and tracks.

surface-curved-pill

Switch thumbs and pill controls.

surface-inset

Native form fields, where pseudo-elements are unavailable.

Card example
<div className="surface-curved relative rounded-card bg-card shadow-soft">
...
</div>