v0.5.1

Theming

The token system, primitives, semantic layer, dark mode, and brand overrides.

Paubha's theming is a two-layer CSS custom property system, mirrored 1:1 from the Figma Foundations / Colors page. Components never touch raw hex or primitive scales, only semantic tokens.

Layer 1: Primitives

Raw scales with no meaning attached: --brand-50 through --brand-950, the same for gray, error, warning, success, plus spacing and radius. One mode. You rarely reference these in components.

Brand

True blue. brand/600 is the primary brand color.

50

#EFF4FF

100

#DBE5FE

200

#BFD0FE

300

#93B0FD

400

#6187F9

500

#3B63F5

600

#2450EA

700

#1C3FD1

800

#1E37A9

900

#1E3485

950

#172152

Gray

Neutral scale with a slight cool bias to harmonize with brand blue.

50

#FAFAFA

100

#F5F5F5

200

#E5E5E5

300

#D4D4D4

400

#A3A3A3

500

#737373

600

#525252

700

#404040

800

#262626

900

#171717

950

#0A0A0A

Error

Red scale for destructive actions, errors, and critical alerts.

50

#FEF3F2

100

#FEE4E2

200

#FECDCA

300

#FDA29B

400

#F97066

500

#F04438

600

#D92D20

700

#B42318

800

#912018

900

#7A271A

950

#55160C

Warning

Amber scale for cautionary states and non-blocking alerts.

50

#FFFAEB

100

#FEF0C7

200

#FEDF89

300

#FEC84B

400

#FDB022

500

#F79009

600

#DC6803

700

#B54708

800

#93370D

900

#7A2E0E

950

#4E1D09

Success

Green scale for confirmation, completion, and positive feedback.

50

#ECFDF3

100

#D1FADF

200

#A6F4C5

300

#6CE9A6

400

#32D583

500

#12B76A

600

#058550

700

#067647

800

#085D3A

900

#074D31

950

#053321

Layer 2: Semantic

Meaning-based aliases onto primitives: --bg-primary, --fg-secondary, --border-default, --focus-ring. Components only ever reference semantic tokens. Dark mode remaps semantic → primitive; no component contains a dark: variant for themed colors.

Turning dark mode on

Nothing to wire up: tokens.css ships a prefers-color-scheme: dark block, so the theme follows the reader's OS setting on its own. color-scheme is set too, so native scrollbars, form controls, and the text caret match.

To let people choose instead of following the OS, put a light or dark class on <html>. An explicit class always beats the OS preference in both directions:

<html class="dark">

With next-themes, that's:

<ThemeProvider attribute="class" defaultTheme="system" enableSystem>

The dark values are declared twice — once under prefers-color-scheme, once under .dark — and pnpm check fails if the two ever drift apart, so switching theme by OS and by class always produce the same result.

Light → Dark remap

TokenLightDark
bg/primarybase/whitegray/950
bg/secondarygray/50gray/900
bg/tertiarygray/100gray/800
bg/elevatedbase/whitegray/900
bg/brand-solidbrand/600brand/600
bg/brand-solid-hoverbrand/700brand/500
bg/brand-subtlebrand/50brand/950
fg/primarygray/900gray/50
fg/secondarygray/600gray/400
fg/tertiarygray/500gray/500
fg/disabledgray/400gray/600
fg/on-brandbase/whitebase/white
fg/brandbrand/600brand/400
border/defaultgray/200gray/800
border/stronggray/300gray/700
border/brandbrand/600brand/400
focus/ringbrand/500brand/400

Status solids (bg/error-solid, bg/warning-solid, bg/success-solid) stay on their */600 step in both modes; subtles flip */50 → */950.

Signature effects

Two things make Paubha look like Paubha:

  • Brand-tinted shadows. Every shadow uses brand/900 at low opacity instead of flat black, so depth stays in the brand's color world.
  • Glow focus ring. --shadow-glow-focus: a 4px spread of brand/500 at 24%, zero blur, zero offset. Applied via the focus-glow utility. Always brand-colored, no error or neutral variants.

Changing the brand color

Override the --brand-* primitive scale after importing tokens.css. Because everything downstream is semantic aliases, components, shadows, and the focus ring follow automatically.

Radius personality

Paubha leans squircle: 6 / 8 / 10 / 14 / 20px (radius-xs → radius-xl), plus radius-full for pills. Inputs and buttons default to radius-md (10px).