Theming
Customise naUI with CSS custom properties - no Sass, no build step.
How theming works
Every naUI value is a CSS custom property defined in :root inside core.css. Override any token in your own stylesheet and every component that references it updates automatically - no Sass, no build step.
Brand colours
Override the base colour tokens. Hover/active states are computed automatically via hsl() relative colour syntax.
/* Override in your own stylesheet, after naui.css loads */
:root {
--color-primary: #7c3aed; /* purple brand */
--color-secondary: #0ea5e9; /* sky accent */
}Colour token map
Base semantic colour tokens - these are the ones you override to theme naUI. Every component references these values.
| Token | Default | Swatch | Used by |
|---|---|---|---|
--color-white | #ffffff | Surfaces, text on dark | |
--color-black | #000000 | Text, borders | |
--color-disabled | #d1d5db | Disabled inputs & buttons | |
--color-default | #6b7280 | Default variant buttons | |
--color-primary | #3b82f6 | Buttons, links, focus rings | |
--color-secondary | #6366f1 | Secondary buttons | |
--color-success | #22c55e | Alerts, badges, status dots | |
--color-warning | #f59e0b | Alerts, badges | |
--color-danger | #ef4444 | Alerts, invalid inputs | |
--color-info | #0ea5e9 | Info alerts, chips | |
--color-brand | #8b5cf6 | Brand accent elements | |
--color-accent | #14b8a6 | Teal accent elements |
Interaction states
Hover and active states are computed automatically from each base token using relative hsl() colour syntax. You do not need to override these unless you want manual control.
| Token pattern | How it is derived |
|---|---|
--color-{name}-hover | Saturation −12, lightness −9 relative to base |
--color-{name}-active | Saturation −10, lightness −16 relative to base |
Subtle variants
Each semantic colour automatically gets three derived subtle tokens used for tinted surfaces, borders, and text - computed via color-mix().
| Token pattern | Formula | Usage |
|---|---|---|
--color-{name}-subtle | 12% tint with white | Alert / badge backgrounds |
--color-{name}-subtle-border | 35% tint with white | Alert / badge borders |
--color-{name}-subtle-text | Lightness −32 via hsl() | Alert / badge text |
Available for: primary, secondary, success, warning, danger, info, brand, accent.
Gray scale
Neutral grays used for surfaces, borders, and text throughout the system.
| Token | Default | Swatch |
|---|---|---|
--na-gray-50 | #f9fafb | |
--na-gray-100 | #f3f4f6 | |
--na-gray-200 | #e5e7eb | |
--na-gray-300 | #d1d5db | |
--na-gray-400 | #9ca3af | |
--na-gray-500 | #6b7280 | |
--na-gray-600 | #4b5563 | |
--na-gray-700 | #374151 | |
--na-gray-800 | #1f2937 | |
--na-gray-900 | #111827 |
Typography tokens
| Token | Default |
|---|---|
--na-font-sans | Montserrat, system-ui, sans-serif |
--na-font-mono | ui-monospace, Cascadia Code, monospace |
--na-font-size-xs - 3xl | 0.75rem – 2.25rem |
--na-font-weight-400 - bold | 400 / 500 / 600 / 700 / 800 |
Spacing scale
| Token | Value |
|---|---|
--na-space-1 | 0.25rem |
--na-space-2 | 0.5rem |
--na-space-3 | 0.75rem |
--na-space-4 | 1rem |
--na-space-5 | 1.25rem |
--na-space-6 | 1.5rem |
--na-space-8 | 2rem |
--na-space-10 | 2.5rem |
--na-space-12 | 3rem |
--na-space-16 | 4rem |
Border radius
naUI defaults to a square (0) design with a pill-only exception.
| Token | Default value |
|---|---|
--na-border-radius | 0 |
--na-border-radius-sm - 2xl | all 0 |
--na-border-radius-full | 9999px |
Dark mode skeleton
[data-theme="dark"] {
--color-primary: #60a5fa;
--na-border-color: #374151;
--na-gray-50: #111827;
--na-gray-100: #1f2937;
--na-gray-900: #f9fafb;
/* - override greys + surface tokens */
}