Theming
How the theme is built, what each token is for, and how to change it.
How it works
The theme is one file, styles/base.css, built in two layers:
- Values.
--nui-*variables hold the actual colors, radius, shadows, and sizes. Light values sit in the:rootblock. The.darkblock overrides only the values that change in dark mode. - Tokens. An
@theme inlineblock turns each value into a Tailwind token.--nui-cardbecomescard, which you use asbg-card,border-card, and so on.
Components use tokens only, never raw colors. Change a value and every component that uses it follows, in light and dark.
Tokens are named for their job, not their color. muted-foreground means secondary text, whatever color you give it.
Most grays point at one scale, --nui-neutral-50 to --nui-neutral-950. Shift that scale to make every gray warmer or cooler at once.
Colors
Naming
Color tokens come in families that share a base name:
| Suffix | Meaning |
|---|---|
| (none) | The fill. |
-foreground | Text and icons on that fill. |
-hover, -active | The fill on hover and while pressed. |
-soft | A light tint of the color, for quiet backgrounds. |
-soft-foreground | Text on the tint. |
When you change a fill, check that its -foreground still reads well on it.
Surfaces
| Token | Used for |
|---|---|
background | The page behind everything. |
foreground | Default text and icons. |
canvas | The content area inside an app shell, set apart from the page. |
canvas-border | The canvas edge. Transparent by default. |
card | Cards, tables, and panels. |
card-foreground | Text on cards. |
card-border | Card edges. |
popover | Menus, dropdowns, date pickers, and other floating panels. |
popover-foreground | Text in floating panels. |
muted | Quiet fills, such as skeletons, progress tracks, segmented controls, and code blocks. |
muted-foreground | Secondary text: descriptions, hints, and placeholders. |
border | The default hairline for dividers and outlines. |
tag | Tag and keyboard key fills. |
tag-border | Tag and keyboard key edges. |
overlay | The dimmed backdrop behind dialogs and drawers. |
inverse | High-contrast fills that flip against the page, such as tooltips. |
inverse-foreground | Text on inverse fills. |
Controls
| Token | Used for |
|---|---|
control | The fill of inputs, selects, checkboxes, and outline buttons. |
control-foreground | Text inside controls. |
control-border | Control edges. |
control-hover | The control fill on hover. |
control-active | The control fill while pressed. |
control-focus | The control edge while focused. Follows ring by default. |
control-disabled | The fill of disabled controls. |
control-disabled-foreground | Text in disabled controls. |
input | Unfilled tracks and lines, such as an off switch, step and timeline connectors, and the upload drop area. |
ring | The keyboard focus ring. Follows primary by default. |
Actions
| Token | Used for |
|---|---|
primary | Main buttons, checked and selected states, active tabs, and progress. |
primary-foreground | Text on primary. |
primary-hover | Primary on hover. |
primary-active | Primary while pressed. |
primary-soft | A light primary tint, such as a selected date range. |
secondary | Secondary buttons. |
secondary-foreground | Text on secondary buttons. |
secondary-hover | Secondary on hover. |
secondary-active | Secondary while pressed. |
accent | Hovered and highlighted items in menus, lists, and calendars. |
accent-foreground | Text on accent. |
accent-hover | Accent on hover. |
Status
| Token | Used for |
|---|---|
destructive | Delete actions, errors, and invalid fields. |
destructive-foreground | Text on destructive. |
destructive-soft | A light destructive tint, such as an error alert background. |
destructive-soft-foreground | Text on the destructive tint. |
success | Completed and healthy states. |
success-foreground | Text on success. |
success-soft | A light success tint, such as a success alert background. |
success-soft-foreground | Text on the success tint. |
warning | Something that needs attention. |
warning-foreground | Text on warning. |
warning-soft | A light warning tint, such as a warning alert background. |
warning-soft-foreground | Text on the warning tint. |
info | Neutral notices and tips. |
info-foreground | Text on info. |
info-soft | A light info tint, such as an info alert background. |
info-soft-foreground | Text on the info tint. |
A destructive button uses the solid fill with its foreground; an alert uses the soft tint with its soft foreground.
Palette
Ten more colors for content that isn't a status. The full calendar uses them for events, and blocks use them for tags, categories, and avatars.
| Token | Used for |
|---|---|
palette-emerald | The emerald fill. |
palette-emerald-foreground | Text on the emerald fill. |
palette-emerald-soft | A light emerald tint. |
palette-emerald-soft-foreground | Text on the emerald tint. |
palette-rose | The rose fill. |
palette-rose-foreground | Text on the rose fill. |
palette-rose-soft | A light rose tint. |
palette-rose-soft-foreground | Text on the rose tint. |
palette-blue | The blue fill. |
palette-blue-foreground | Text on the blue fill. |
palette-blue-soft | A light blue tint. |
palette-blue-soft-foreground | Text on the blue tint. |
palette-cyan | The cyan fill. |
palette-cyan-foreground | Text on the cyan fill. |
palette-cyan-soft | A light cyan tint. |
palette-cyan-soft-foreground | Text on the cyan tint. |
palette-orange | The orange fill. |
palette-orange-foreground | Text on the orange fill. |
palette-orange-soft | A light orange tint. |
palette-orange-soft-foreground | Text on the orange tint. |
palette-red | The red fill. |
palette-red-foreground | Text on the red fill. |
palette-red-soft | A light red tint. |
palette-red-soft-foreground | Text on the red tint. |
palette-purple | The purple fill. |
palette-purple-foreground | Text on the purple fill. |
palette-purple-soft | A light purple tint. |
palette-purple-soft-foreground | Text on the purple tint. |
palette-yellow | The yellow fill. |
palette-yellow-foreground | Text on the yellow fill. |
palette-yellow-soft | A light yellow tint. |
palette-yellow-soft-foreground | Text on the yellow tint. |
palette-lime | The lime fill. |
palette-lime-foreground | Text on the lime fill. |
palette-lime-soft | A light lime tint. |
palette-lime-soft-foreground | Text on the lime tint. |
palette-gray | The gray fill. |
palette-gray-foreground | Text on the gray fill. |
palette-gray-soft | A light gray tint. |
palette-gray-soft-foreground | Text on the gray tint. |
The solid fill's variable ends in -solid, for example --nui-palette-blue-solid.
Charts
Chart series take these colors in order. By default they reuse primary and the palette, so charts match the rest of the theme.
| Token | Used for |
|---|---|
chart-1 | Series 1. Defaults to primary. |
chart-2 | Series 2. Defaults to palette-purple. |
chart-3 | Series 3. Defaults to palette-emerald. |
chart-4 | Series 4. Defaults to palette-yellow. |
chart-5 | Series 5. Defaults to palette-red. |
chart-6 | Series 6. Defaults to palette-orange. |
chart-7 | Series 7. Defaults to palette-cyan. |
chart-8 | Series 8. Defaults to palette-rose. |
chart-9 | Series 9. Defaults to palette-lime. |
chart-10 | Series 10. Defaults to palette-gray. |
Shape and type
Radius
| Token | Used for |
|---|---|
rounded-control | Buttons, inputs, and selects. |
rounded-control-sm | Items inside controls and menus, segments, and tooltips. |
rounded-card | Cards. |
rounded-popover | Menus, dropdowns, and date pickers. |
rounded-overlay | Dialogs and drawers. |
rounded-tag | Tags and keyboard keys. |
rounded-badge | Badges and the switch track. Fully round by default. |
rounded-canvas | The canvas inside an app shell. |
These point at a base scale, --nui-radius-xs to --nui-radius-2xl.
Shadows
| Token | Used for |
|---|---|
shadow-card | Cards. |
shadow-control | Controls at rest. None by default. |
shadow-popover | Menus and other floating panels. |
shadow-dialog | Dialogs. |
shadow-drawer | Drawers. |
shadow-canvas | The canvas inside an app shell. |
Dark mode has its own shadows, which add a faint light edge so surfaces stay visible on dark backgrounds.
Sizes
| Token | Used for |
|---|---|
control-sm | Small control height, 32 px. |
control-md | Medium control height, 36 px. |
control-lg | Large control height, 48 px. |
Use them with h-, min-h-, or w-, for example h-control-md.
Stacking
| Token | Used for |
|---|---|
z-sticky | Sticky headers. |
z-dropdown, z-popover, z-overlay, z-modal | Floating panels, dialogs, and drawers. |
z-toast | Toasts. |
z-tooltip | Tooltips, above everything else. |
If your app's own layers need to sit above or below these, change the matching --nui-z-* values.
Font
font-sans is the interface font: Inter, falling back to system fonts. font-mono is used for code. To use another font, change --font-sans.
Dark mode
Use an explicit dark or light class on <html>. If your appearance controller updates the root directly, keep both classes and the attribute aligned with the same mode value passed to your component provider:
The .dark class activates Tailwind dark: utilities as well as the dark tokens. A data-theme attribute alone selects tokens and is not a complete appearance switch. With the exported Theme Workbench wrapper, change its mode prop instead; it synchronizes the root signals as described below.
The .dark block lists only what changes. Surfaces, borders, controls, and the soft tints get dark values; primary and the solid status colors stay the same in both modes.
Change a value
Edit the variables in styles/base.css. For example, to change the primary color:
--nui-primary isn't in the .dark block, so this changes both modes. To give dark mode its own value, add the same variable to the .dark block.
Change a fill and its -foreground, -hover, and -active together, so text stays readable and states stay distinct.
Theme workbench
The theme workbench lets you build a theme visually instead of editing values by hand.
- Pick a starting style: Default, Soft Flat, Neomorphism, Neobrutalism, Glass, or Editorial.
- Adjust colors, font, density, and control sizes. Check them against real components in light and dark.
- Open Code to preview or download
nateui-theme.zip. It containsbase.css,config-provider.tsxandDESIGN.mdfrom the same effective settings and selected Light/Dark mode. - Replace your
styles/base.csswith the downloadedbase.css. - Save
config-provider.tsxin your project and wrap your app with it:
The file carries the defaults and extra class names your chosen style depends on, so styles such as Neobrutalism look right beyond their colors.
Use the exported provider once at the application root. Its default mode is the selected appearance; on client mount and mode changes it synchronizes the root .light/.dark class and data-theme attribute before paint. For server-rendered pages, initialize the <html> class to that same mode before first paint, then hydrate with the matching provider mode. Pass a new mode prop to switch appearance at runtime.
Both palettes remain in base.css. With no root signal, CSS supplies the selected mode's token fallback; complete appearance also requires the provider's root-class initialization or matching server markup. The .dark class activates Tailwind dark: utilities. Setting data-theme alone selects tokens and is not a complete appearance switch. Keep an existing appearance controller as the mode source when adopting this wrapper, and avoid competing or nested root-mode owners. Font files are not included; retain your application's font loading and adjust import aliases to your project.
DESIGN.md records the selected preset and guide versions, effective configuration and composition guidance. It replaces affected baseline claims when token, font, default or slot customizations change their assumptions. Exact values stay in the paired CSS and provider files. This selected direction differs from the provisional Default document seeded by skill installation.
Review and deliberately merge or adopt the exported document. Preserve an existing project-owned DESIGN.md until you choose to revise it, and record your actual implementation paths after adoption. Keep its relative links beside the paired files or update them when moving the document. Downloading a guide applies no styles and does not replace project files.
Component defaults
ConfigProvider sets defaults for every component below it, so you don't repeat the same props across your app.
componentDefaultssets default props per component.classNamesadds classes to named parts of a component everywhere it appears.
A prop set directly on a component always wins over the default.