A design token is a named value that the whole interface shares: a colour, a spacing step, a font size, a duration. NuvoUI emits every token as a CSS custom property that starts with --nu-, and every utility class and mixin outputs those properties instead of raw values. Change a token and everything that uses it changes; switch the theme and the tokens that belong to the theme change with it.
SCSS is the source. Tokens are generated from the configuration maps and colour variables when core is compiled. There is no separate token file to maintain.
Emitted on :root. Fixed tokens (palette, basic colours, scales, font family) sit in a :root-only block. Theme tokens sit in the light block (:root, [data-theme="light"]), and the dark theme redefines only those. Because fixed tokens are declared once on :root, a runtime :root override of one also applies inside [data-theme="light"] sections. See Theming.
Emitted without utility classes. Tokens are part of the theme feature, not of the utility classes, so a project that uses only mixins ($generate-utility-classes: false) still gets every token.
Decimal keys. A decimal key uses _ in the token name: spacing key 0.5 is --nu-space-0_5.
The palette never changes. Dark mode works by pointing role and theme tokens at different palette shades: in the default configuration --nu-brand is var(--nu-brand-700) in the light theme and var(--nu-brand-400) in the dark theme, and --nu-brand-700 itself stays the same colour in both.
:root {
--nu-brand-700: #0058bb;
--nu-brand-400: #5ca0ff;
}
:root,
[data-theme="light"] {
--nu-brand: var(--nu-brand-700);
}
[data-theme="dark"] {
--nu-brand: var(--nu-brand-400);
}
Palette hues (red, blue) are plain colours with no meaning. Roles (brand, danger) carry a meaning and point at a palette shade. Brand is a role, not an extra hue.
Prefix and hyphens. Every core token is --nu- followed by words joined with single hyphens: --nu-text-muted, --nu-brand, --nu-space-4.
Component variables. Variables that belong to a component always contain a double underscore or a double hyphen after the component name: --nu-btn--BackgroundColor, --nu-sidebar__link--Color. They can never collide with a core token. Core’s tooltips follow this grammar (--nu-tooltip--Background); component packages built on core use it for their own variables.
Internal variables. A few utilities use internal custom properties that also start with --nu-, such as --nu-flex-gap, --nu-border-style and --nu-translate-x. They are not tokens: token() rejects them, and they are not part of the theme.
Short class names. Only the variables carry the prefix. Classes stay short: text-muted, bg-danger, p-4.
Every role has the same set of tokens. The bare role name is the solid fill:
Token
Purpose
--nu-{role}
Solid fill at rest
--nu-{role}-hover, --nu-{role}-active
The fill when hovered and pressed
--nu-{role}-subtle
Tinted background
--nu-{role}-border
Soft edge
--nu-text-{role}
Role-coloured text on a normal page
--nu-text-on-{role}
Text placed on the {role} fill
The roles are brand, success, danger, warning and info; error is an alias of danger. The utility classes bg-{role}, bg-{role}-subtle, text-{role} and text-on-{role} cover the most used tokens; the hover, active and border tokens are used through mixins and token().
token() takes the token name without --nu- and returns var(--nu-{name}), with no fallback value. It accepts exactly the names that core emits, so an unknown name fails the build instead of the page.
Input
Error
token(text-mutd)
token(text-mutd): unknown token. Close matches: text-muted.
token(--nu-text-muted)
token(--nu-text-muted): pass the name without the prefix, e.g. token(text-muted).
token(delay-150)
token(delay-150): unknown token. Valid names are the --nu- custom properties in :root, without --nu-.
token(brand-default)
token(brand-default): renamed in 2.0, use token(brand).
token(error-default)
token(error-default): renamed in 2.0, use token(danger).
With the theme feature flag off no tokens are emitted, and token() raises token(name): no tokens are emitted because the theme feature flag is off.
get-color() resolves role and palette names before CSS named colours, so get-color(red) is palette red (#ef4444), not the CSS colour red. It takes the same stops as the palette and never returns var(). Because the result is fixed at compile time, it does not change with the theme and ignores theme overrides; use it only where a real colour value is needed.
Generated from the compiled core build with the default configuration. The Dark column shows the value in the dark theme where it differs; “Same” means the token is defined once and does not change. A consumer configuration ($brand, the theme maps, the scale maps) changes these values.