mirror of
https://github.com/Nexoniarz/Niveus.git
synced 2026-11-03 04:34:26 +00:00
Tokens - --nv-color-glow role (light and dark) and a glow scale: --nv-glow-sm/md/lg, --nv-glow-blur-*, --nv-glow-spread-*, --nv-glow-strength - --nv-stagger (0ms under reduced motion) and --nv-duration-shimmer Components - Card: --lit (lit top edge in --nv-card-tint), --glow, --spotlight (light follows the pointer); light layers combine with every elevation - Tile: small raised key for a glyph or product mark; --solid, --glow, sizes - Avatar: raised disc with --ring / --glow, sizes, __status, avatar group - Stat: readings set into one recessed well (.nv-stat-group) - Steps: markers set into a rail; done steps light their stretch; vertical - Deck: one surface in front of stacked layers of its kind - Skeleton: recessed placeholder with a slow sweep, still under reduced motion - Text: .nv-text-lit and .nv-text-lit--accent Continuity - .nv-reveal / .nv-reveal-group: content arrives once as it scrolls into view (nv-arrive keyframe); niveus.js marks pending state, so nothing is hidden without the script or under reduced motion - niveus.js tracks the pointer for .nv-card--spotlight README and REFERENCE document every new class, token and attribute; tools/check.py passes and dist/ is rebuilt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
516 lines
27 KiB
Markdown
516 lines
27 KiB
Markdown
# Niveus — reference
|
||
|
||
Every class, token, attribute and function the system exposes, with the name
|
||
the rest of the industry uses for it.
|
||
|
||
Two audiences:
|
||
|
||
- **People.** Find the thing you mean by its usual name, then use the class
|
||
beside it.
|
||
- **Models.** This file is the whole API. Hand it over on its own and an
|
||
assistant can build correct Niveus markup without seeing the CSS: it does not
|
||
need to know *how* `.nv-nav-tabs` works, only that a tab list is spelled that
|
||
way here. Nothing below is aspirational — `tools/check.py` fails if a class
|
||
exists in the CSS and is missing from this file.
|
||
|
||
Everything ships inside the `niveus` cascade layer, so unlayered application
|
||
styles win without `!important`.
|
||
|
||
```html
|
||
<link rel="stylesheet" href="dist/niveus.css"> <!-- keep fonts/ beside dist/ -->
|
||
<script src="niveus/niveus.js" defer></script> <!-- optional -->
|
||
<html data-theme="dark"> <!-- omit to follow the OS -->
|
||
<style>:root { --nv-brand: #d92e3f; }</style> <!-- the whole identity -->
|
||
```
|
||
|
||
---
|
||
|
||
## Button
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-button` | button, secondary button | Raised surface. The default; use it for anything that is not *the* action. |
|
||
| `.nv-button--primary` | filled / CTA button | The single affirmative action in a view. |
|
||
| `.nv-button--subtle` | tonal button | Accent-tinted fill, no elevation. Mid-emphasis. |
|
||
| `.nv-button--ghost` | text / quiet button | No material until hovered. Lowest emphasis. |
|
||
| `.nv-button--danger` | destructive button | Irreversible actions only. |
|
||
| `.nv-button--frosted` | glass button | For use over imagery or frosted chrome. |
|
||
| `.nv-button--float` | FAB, overlay control | Floats over content: grows on hover instead of lifting, and keeps its own positioning via `--nv-button-offset`. |
|
||
| `.nv-button--sm` `.nv-button--lg` | size variants | 28px and 44px; default is 36px. |
|
||
| `.nv-button--icon` | icon button | Square. Requires `aria-label`. |
|
||
| `.nv-button--pill` | pill button | Fully rounded. |
|
||
| `.nv-button--block` | full-width button | Fills its container. |
|
||
| `.nv-button__icon` | button icon slot | Sizes an inline SVG to the label. |
|
||
| `.nv-button-group` | segmented control, button group | Buttons sharing edges; only outer corners round. |
|
||
|
||
States come from the element: `disabled`, `aria-disabled`, `aria-busy="true"`
|
||
(shows a spinner and keeps the width), `aria-pressed` for toggles.
|
||
|
||
## Form controls
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-field` | form field, form group | Label + control + hint, correctly spaced. |
|
||
| `.nv-field__label` | field label | Add `data-optional="(optional)"` to append a muted suffix. |
|
||
| `.nv-field__hint` | helper text | Guidance below the control. |
|
||
| `.nv-field__error` | validation message | Pair with `aria-invalid="true"` + `aria-describedby`. |
|
||
| `.nv-input` | text field, form control | `input`, `textarea` and `select`. Inset material. |
|
||
| `.nv-input--sm` `.nv-input--lg` | size variants | Match the button sizes. |
|
||
| `.nv-input--color` | color well / swatch input | `input[type=color]` as a square swatch. |
|
||
| `.nv-input-group` | input with adornment | Wrapper for a field with a prefix or suffix. |
|
||
| `.nv-input-group__affix` | prefix / suffix adornment | Sits inside the field's recess. First child = leading, last = trailing. |
|
||
| `.nv-select` | select, dropdown | Wrapper that draws the chevron around a native `select.nv-input`. |
|
||
| `.nv-checkbox` | checkbox | Native input, custom mark. Supports `:indeterminate`. |
|
||
| `.nv-radio` | radio button | Native input, custom mark. |
|
||
| `.nv-switch` | toggle switch | Inset track, elevated thumb that travels. |
|
||
| `.nv-choice` | control with inline label | `<label>` wrapping a control and its text. |
|
||
|
||
## Card
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-card` | card, panel | Resting container at elevation 1. |
|
||
| `.nv-card--elevated` | raised card | Elevation 2 — read before its surroundings. |
|
||
| `.nv-card--floating` | floating card | Elevation 3. |
|
||
| `.nv-card--inset` | well, sunken panel | Recessed into its parent. |
|
||
| `.nv-card--frosted` | glass card | Translucent, for use over imagery or a bed. |
|
||
| `.nv-card--interactive` | clickable card | Lifts on hover, sinks on press. |
|
||
| `.nv-card--flush` | edge-to-edge card | Removes part padding, for media or tables. |
|
||
| `.nv-card--lit` | accent-edge card, colored top border | A strip of light along the top edge in the card's tint, spilling a little down the face. For a card that belongs to something with a color. |
|
||
| `.nv-card--glow` | glowing card, highlighted card | Gives off its tint. For the one card that is *on* — the current plan, the live item. |
|
||
| `.nv-card--spotlight` | spotlight card, cursor glow | A soft light follows the pointer across the face (needs `niveus.js`). Showcases only. |
|
||
| `.nv-card__header` | card header | |
|
||
| `.nv-card__title` | card title | |
|
||
| `.nv-card__subtitle` | card subtitle, supporting text | |
|
||
| `.nv-card__body` | card content | |
|
||
| `.nv-card__footer` | card actions | |
|
||
| `.nv-card__footer--plain` | undivided card actions | Drops the divider above the footer. |
|
||
| `.nv-card__media` | card media | 16:9 image slot. |
|
||
| `.nv-card__link` | stretched link | Expands one link's hit area over the whole card. |
|
||
| `.nv-card-grid` | responsive card grid | Auto-fitting, equal-height columns. |
|
||
|
||
`--lit`, `--glow` and `--spotlight` combine with every elevation and with each
|
||
other. They take `--nv-card-tint` (the accent unless set on the card).
|
||
|
||
## Deck
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-deck` | card stack, stacked cards | One surface in front of others of its kind. Every child shares one grid cell. |
|
||
| `.nv-deck__layer` | stack layer | A decorative card behind the front one, stepping back and dimming with depth. Up to two; mark them `aria-hidden="true"`. |
|
||
|
||
Hidden `.nv-tab-panel`s can live in a deck together: the front surface is
|
||
whichever one is showing.
|
||
|
||
## Dialog
|
||
|
||
Built on native `<dialog>`; open with `showModal()` or `nv.openDialog()`.
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-dialog` | modal dialog | Elevation 4 over a blurred scrim. Focus trap and Escape are the platform's. |
|
||
| `.nv-dialog--sheet` | bottom sheet | Enters from the block end, flush to the edges. |
|
||
| `.nv-dialog--compact` `.nv-dialog--wide` | width variants | 24rem / 44rem; default 30rem. |
|
||
| `.nv-dialog__header` | dialog header | |
|
||
| `.nv-dialog__title` | dialog title | Point `aria-labelledby` at it. |
|
||
| `.nv-dialog__description` | dialog supporting text | |
|
||
| `.nv-dialog__body` | dialog content | The only scrolling region. |
|
||
| `.nv-dialog__footer` | dialog actions | |
|
||
| `.nv-dialog__footer--divided` | grounded dialog actions | For a footer sitting over scrollable content. |
|
||
| `.nv-dialog__close` | close button | Optical alignment for a ghost icon button. |
|
||
|
||
## Menu
|
||
|
||
Built on the `popover` attribute and anchor positioning. Trigger and menu name
|
||
the same anchor through `--nv-anchor`.
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-menu` | dropdown menu, popover menu | Frosted surface anchored to its trigger. |
|
||
| `.nv-menu-trigger` | menu button | Sets `anchor-name` from `--nv-anchor`. |
|
||
| `.nv-menu__item` | menu item | `aria-checked="true"` draws a tick. |
|
||
| `.nv-menu__item--danger` | destructive menu item | |
|
||
| `.nv-menu__label` | menu section label / group heading | |
|
||
| `.nv-menu__separator` | menu divider | |
|
||
| `.nv-menu__shortcut` | keyboard shortcut hint, accelerator | Trailing muted text. |
|
||
|
||
## Navigation
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-nav` | app bar, navigation bar, header | Frosted, sticky chrome. |
|
||
| `.nv-nav--vertical` | sidebar, side navigation | Full-height, solid; drops the translucency. |
|
||
| `.nv-nav--plain` | solid bar | Opaque instead of frosted. |
|
||
| `.nv-nav--static` | non-sticky bar | |
|
||
| `.nv-nav--inline` | inline nav group | A navigation used inside content, not as chrome. |
|
||
| `.nv-nav__brand` | brand / logo lockup | |
|
||
| `.nv-nav__list` | nav list | |
|
||
| `.nv-nav__item` | nav item, nav link | Selected via `aria-current`, `aria-selected` or `--active`. |
|
||
| `.nv-nav__item--active` | active nav item | For when no ARIA state fits. |
|
||
| `.nv-nav__section` | nav section heading | |
|
||
| `.nv-nav__icon` | nav icon slot | |
|
||
| `.nv-nav__badge` | count badge, notification badge | |
|
||
| `.nv-nav__spacer` | flexible spacer | Pushes what follows to the end. |
|
||
| `.nv-nav-tabs` | tab list, segmented tabs | Inset track; the selected tab lifts out of it. |
|
||
| `.nv-tab-panel` | tab panel | Hands over to the next panel inside the same box when `nv.selectTab` switches tabs. |
|
||
| `.nv-breadcrumbs` | breadcrumbs | |
|
||
|
||
## Disclosure
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-disclosure` | disclosure, accordion item | A `<details>` whose height animates open and closed. |
|
||
| `.nv-disclosure--plain` | bare disclosure | No surface of its own. |
|
||
| `.nv-disclosure__summary` | disclosure trigger | The `<summary>`. |
|
||
| `.nv-disclosure__chevron` | chevron, caret | Rotates rather than swapping glyphs. |
|
||
| `.nv-disclosure__body` | disclosure content | |
|
||
| `.nv-disclosure-group` | accordion | Stacked disclosures sharing hairlines. |
|
||
| `.nv-collapse` | collapsible region | Same relationship for markup that cannot be a `<details>`. Toggle `data-open`. |
|
||
|
||
## Scroller
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-scroller-frame` | carousel frame | Positions the controls; holds the track. |
|
||
| `.nv-scroller` | carousel, snap scroller, rail | Horizontal row with scroll snapping and fading edges. |
|
||
| `.nv-scroller--auto` | content-width items | Items size to content instead of the track. |
|
||
|
||
Set `--nv-scroller-item` for item width, `--nv-scroller-fade` for the edge fade.
|
||
|
||
## Badge
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-badge` | badge, chip, tag, status pill | Non-interactive statement of state. |
|
||
| `.nv-badge--accent` | accent badge | |
|
||
| `.nv-badge--success` `.nv-badge--warning` `.nv-badge--danger` | status badges | Tone follows the semantic role. |
|
||
| `.nv-badge--solid` | filled badge | For the one badge that must be seen first. |
|
||
| `.nv-badge--count` | count badge | Tabular, borderless, min two digits. |
|
||
| `.nv-badge--square` | square badge | |
|
||
| `.nv-badge__dot` | status dot | |
|
||
|
||
## Tile
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-tile` | icon tile, icon badge, feature icon | A small raised key holding one glyph: tinted face, glyph in its tint. Not interactive. |
|
||
| `.nv-tile--solid` | filled icon tile | Saturated face with a light glyph. |
|
||
| `.nv-tile--glow` | glowing icon tile | Lit from inside. |
|
||
| `.nv-tile--sm` `.nv-tile--lg` `.nv-tile--xl` | tile sizes | 32 / 56 / 72px; default 44px. |
|
||
|
||
`--nv-tile-tint` picks the color. An `<img>` inside fills the key, an `<svg>`
|
||
takes half of it.
|
||
|
||
## Avatar
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-avatar` | avatar, profile picture | Round raised disc holding an `<img>` or initials. |
|
||
| `.nv-avatar--ring` | avatar ring, story ring | A ring in `--nv-avatar-tint`, set off by a gap of surface. |
|
||
| `.nv-avatar--glow` | glowing avatar | The ring, giving off its tint. |
|
||
| `.nv-avatar--sm` `.nv-avatar--lg` `.nv-avatar--xl` | avatar sizes | 28 / 64 / 96px; default 40px. |
|
||
| `.nv-avatar__status` | presence dot | Grey at rest. |
|
||
| `.nv-avatar__status--online` | online indicator | Lit green. |
|
||
| `.nv-avatar-group` | avatar stack, facepile | Overlapping row. |
|
||
|
||
## Stat
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-stat-group` | stats row, KPI strip, readout | One recessed well holding several readings, split by hairlines. Wraps on its own. Use a `<dl>`. |
|
||
| `.nv-stat` | stat, metric, KPI | One reading: label, value, optional delta, in that order. |
|
||
| `.nv-stat__label` | metric label | `<dt>` inside a group. |
|
||
| `.nv-stat__value` | metric value, big number | `<dd>`; tabular numerals. |
|
||
| `.nv-stat__delta` | change, trend | |
|
||
| `.nv-stat__delta--up` `.nv-stat__delta--down` | positive / negative trend | Success and danger text. |
|
||
|
||
## Steps
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-steps` | stepper, timeline, process, progress steps | Markers set into a rail cut into the surface. Horizontal, vertical below 40rem. Use an `<ol>`. |
|
||
| `.nv-steps--vertical` | vertical stepper, timeline | Always vertical. |
|
||
| `.nv-steps__item` | step | `data-state="done"` lights it and its stretch of rail; `aria-current="step"` lights the marker only. |
|
||
| `.nv-steps__marker` | step number, step knob | |
|
||
| `.nv-steps__body` | step content | |
|
||
| `.nv-steps__title` | step title | |
|
||
| `.nv-steps__text` | step description | |
|
||
|
||
## Skeleton
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-skeleton` | skeleton, loading placeholder, shimmer | A shallow well where content will be, with a slow band of light crossing it. Still under reduced motion. |
|
||
| `.nv-skeleton--text` | text line placeholder | The last of several lines ends short. |
|
||
| `.nv-skeleton--circle` | avatar placeholder | |
|
||
|
||
## Table
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-table-frame` | table wrapper | Scrolls sideways so the page does not have to. |
|
||
| `.nv-table` | data table | |
|
||
| `.nv-table--compact` | dense table | |
|
||
| `.nv-table--interactive` | clickable rows | |
|
||
| `.nv-table__number` | numeric cell | End-aligned, tabular figures. |
|
||
| `.nv-table__actions` | row actions cell | Shrinks to content. |
|
||
|
||
## Bed
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-bed` | showcase surface, patterned backdrop | Ground that is visibly not ordinary background: for regions the user should look *at*. Gives translucent materials something to be translucent against. |
|
||
| `.nv-bed--quiet` | subdued bed | No hatch, softer blooms. |
|
||
| `.nv-bed--vivid` | emphatic bed | |
|
||
| `.nv-bed--single` | single-hue bed | One color instead of three. |
|
||
| `.nv-bed--flush` | full-bleed bed | Square, no side borders. |
|
||
| `.nv-bed__label` | bed label, eyebrow | |
|
||
|
||
Set `--nv-bed-tint` to lead with a color other than the accent.
|
||
|
||
## Window
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-window` | window, app frame | A framed, solid window. Content never sits on glass. |
|
||
| `.nv-window--inactive` | unfocused window | Greys the lights and the title, drops one elevation. Hovering the lights restores their color. |
|
||
| `.nv-window__titlebar` | titlebar, header bar | Raised strip: controls · title · actions, with the title on the window's center line. |
|
||
| `.nv-window__controls` | traffic lights, window buttons | Group at the start of the bar. Its glyphs show while the pointer is over the group. |
|
||
| `.nv-window__control` | window button | One light. Needs `aria-label`, plus one of the three below. |
|
||
| `.nv-window__control--close` | close button | Red, ×. Always first. |
|
||
| `.nv-window__control--minimize` | minimize button | Yellow, −. Always second. |
|
||
| `.nv-window__control--zoom` | zoom, maximize button | Green, +. Always third. |
|
||
| `.nv-window__title` | window title | Truncates. |
|
||
| `.nv-window__actions` | titlebar actions | Trailing slot; put `.nv-button--ghost.nv-button--sm` here. |
|
||
| `.nv-window__body` | window content | Fills the rest and scrolls. |
|
||
|
||
The three lights keep fixed colors on purpose: they are found by position and
|
||
color before they are read, so they never take the brand.
|
||
|
||
## Surface, material and elevation
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-surface` | surface, panel | Plain container on the solid material. |
|
||
| `.nv-material-solid` | opaque surface | Content lives here. The default. |
|
||
| `.nv-material-elevated` | raised surface | Separated from its context. |
|
||
| `.nv-material-inset` | recessed surface | Fields, wells, tracks. |
|
||
| `.nv-material-frosted` | frosted glass, blur backdrop | Chrome that floats over content: bars, docks, launchers, notifications, menus. Moderate blur, bevelled rim. |
|
||
| `.nv-material-glass` | glass | Contextual layers where content behind must stay legible. |
|
||
| `.nv-elevation-0` `.nv-elevation-1` `.nv-elevation-2` | elevation / z-depth | flush · resting · raised |
|
||
| `.nv-elevation-3` `.nv-elevation-4` `.nv-elevation-5` | elevation / z-depth | floating · lifted · overlay |
|
||
| `.nv-elevation-inset-sm` `.nv-elevation-inset-md` `.nv-elevation-inset-lg` | inner shadow | Recessed surfaces. |
|
||
| `.nv-divider` | divider, separator, rule | |
|
||
| `.nv-divider--vertical` | column rule | Stretches to its flex row. |
|
||
|
||
Material and elevation are independent: combine freely.
|
||
|
||
Niveus is solid, with glass used sparingly: anything that holds content
|
||
(windows, cards, dialogs) is solid, and only chrome floating over it is
|
||
frosted. Raised things are bevelled — lit along the top edge, shaded along the
|
||
bottom, with a contact outline — and carry a sheen across their face. When
|
||
composing your own raised element, use `box-shadow: var(--nv-bevel),
|
||
var(--nv-outline), var(--nv-elevation-2)` with `background-image:
|
||
var(--nv-sheen-raised)` over its role color.
|
||
|
||
## Type roles
|
||
|
||
| Class | Known as | Size |
|
||
| --- | --- | --- |
|
||
| `.nv-display` | display, hero text | 38px |
|
||
| `.nv-heading` | heading | 24px |
|
||
| `.nv-title` | title, subheading | 17px |
|
||
| `.nv-body` | body copy | 15px |
|
||
| `.nv-label` | label, UI text | 13px |
|
||
| `.nv-caption` | caption, secondary text | 12px |
|
||
| `.nv-overline` | overline, eyebrow, engraved label | 11px mono, uppercase, wide tracking |
|
||
| `.nv-code` | code, monospace | 13px |
|
||
| `.nv-text-primary` `.nv-text-secondary` `.nv-text-tertiary` | text color roles | Emphasis, not size. |
|
||
| `.nv-text-accent` `.nv-text-success` `.nv-text-warning` `.nv-text-danger` | semantic text colors | |
|
||
| `.nv-text-lit` | gradient text, metallic text | Lit from above, settling into the accent. One display line per page. |
|
||
| `.nv-text-lit--accent` | accent gradient text | The accent alone, lit from above — for a phrase inside a display line. |
|
||
|
||
## Reveal
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-reveal` | scroll reveal, animate on scroll | Rises and fades in once, as it scrolls into view. Needs `niveus.js`; without it, or under reduced motion, nothing is hidden. |
|
||
| `.nv-reveal-group` | staggered reveal | Its children arrive one after another, `--nv-stagger` apart. |
|
||
|
||
## Layout utilities
|
||
|
||
| Class | Known as | Does |
|
||
| --- | --- | --- |
|
||
| `.nv-container` | page container, wrapper | Max width + gutters. |
|
||
| `.nv-stack` | stack, vertical rhythm | Column with a gap. |
|
||
| `.nv-stack--tight` `.nv-stack--loose` | stack density | |
|
||
| `.nv-cluster` | cluster, wrap row | Wrapping row, vertically centred. |
|
||
| `.nv-cluster--tight` | dense cluster | |
|
||
| `.nv-cluster--between` | spread cluster | Pushes children to both ends. |
|
||
| `.nv-truncate` | ellipsis, text truncation | One line with an ellipsis. |
|
||
| `.nv-prose` | prose, measure | Readable line length and leading. |
|
||
| `.nv-visually-hidden` | screen-reader-only, sr-only | Available to assistive tech, invisible on screen. |
|
||
| `.nv-continuous` | content region | Content that hands over in place (out, then in) when it changes. |
|
||
| `.nv-content` | view-transition class | Not an HTML class: the `view-transition-class` that gives a named element the hand-over animation. Set `view-transition-class: nv-content` on your own named element to get it. |
|
||
| `.nv-carried` | (view-transition class) | Applied to nav items so they ride above a travelling marker. |
|
||
| `.nv-travelling` | (view-transition class) | Applied to a selection marker so it travels below the labels. |
|
||
|
||
---
|
||
|
||
## Tokens
|
||
|
||
Names are stable; values are not. Never state a color, shadow, radius, size or
|
||
duration directly — reference the token.
|
||
|
||
### Color roles
|
||
|
||
`--nv-color-` +
|
||
|
||
```
|
||
background background-subtle surface surface-elevated surface-inset
|
||
surface-hover surface-active scrim
|
||
|
||
text-primary text-secondary text-tertiary text-disabled text-inverted
|
||
border-subtle border border-strong
|
||
|
||
accent accent-hover accent-active accent-subtle accent-subtle-hover
|
||
accent-border accent-text on-accent
|
||
|
||
success success-hover success-subtle success-border success-text on-success
|
||
warning warning-hover warning-subtle warning-border warning-text on-warning
|
||
danger danger-hover danger-active danger-subtle danger-border
|
||
danger-text on-danger
|
||
|
||
shadow-ambient shadow-penumbra shadow-umbra shadow-inset
|
||
highlight highlight-strong lowlight outline elevation-tint-1 … -5
|
||
sheen-top sheen-bottom sheen-strong-top sheen-strong-bottom
|
||
knob knob-shade
|
||
material-frosted material-glass material-border
|
||
window-close window-minimize window-zoom window-inactive
|
||
window-control-ring window-glyph
|
||
focus-ring focus-ring-contrast selection
|
||
glow
|
||
```
|
||
|
||
`on-*` is the text that goes on top of that color, and is derived — never set
|
||
it by hand.
|
||
|
||
### Color inputs
|
||
|
||
| Token | Default | Does |
|
||
| --- | --- | --- |
|
||
| `--nv-brand` | `#4f6cff` | The one color everything derives from. |
|
||
| `--nv-brand-tint` | `4%` | How much brand bleeds into the greys. |
|
||
| `--nv-brand-harmony` | `12%` | How far status colors lean towards the brand. |
|
||
| `--nv-contrast-pivot` | `0.7` | Lightness where a color can no longer carry a label. |
|
||
| `--nv-contrast-dark` / `-light` | `0.53` / `0.78` | How far either side a color is pushed. |
|
||
|
||
`--nv-palette-{neutral|accent|success|warning|danger}-{0…1000}` and
|
||
`--nv-palette-window-{close|minimize|zoom}` are raw values. Components must
|
||
never reference them.
|
||
|
||
### Scales
|
||
|
||
| Family | Steps |
|
||
| --- | --- |
|
||
| `--nv-space-` | `0 px 0-5 1 1-5 2 2-5 3 4 5 6 7 8 10 12 14 16 20 24 32` (suffix = px ÷ 4) |
|
||
| `--nv-radius-` | `none xs sm md lg xl 2xl full`, plus `nested-md` `nested-lg` |
|
||
| `--nv-font-size-` | `2xs xs sm md lg xl 2xl 3xl 4xl 5xl` |
|
||
| `--nv-font-weight-` | `regular medium semibold bold` |
|
||
| `--nv-line-height-` | `tight snug normal relaxed` |
|
||
| `--nv-letter-spacing-` | `tighter tight normal wide wider engraved` |
|
||
| `--nv-font-` | `display heading title body label caption code engraved` (composite shorthands) |
|
||
| `--nv-font-family-` | `sans` (Instrument Sans) `mono` (JetBrains Mono), both shipped in `fonts/` |
|
||
| `--nv-measure` | `-narrow` · `--nv-measure` · `-wide` |
|
||
| `--nv-control-height-` | `sm md lg` — also `control-padding-` and `control-gap-` |
|
||
| `--nv-elevation-` | `0 1 2 3 4 5`, `inset-sm` `inset-md` `inset-lg` |
|
||
| `--nv-highlight-` | `top` `top-strong` `edge` |
|
||
| bevel | `--nv-bevel` (lit top + shaded bottom) · `--nv-lowlight-bottom` · `--nv-outline` (contact line) · `--nv-ledge` (lit lower lip of a recess) |
|
||
| `--nv-sheen-` | `raised filled surface knob` — gradients laid over a role color as `background-image` |
|
||
| `--nv-blur-` | `sm md lg xl` — also `backdrop-frosted` `backdrop-glass` `backdrop-scrim` |
|
||
| `--nv-material-` | `{solid,elevated,inset,frosted,glass}-{bg,border,shadow}` |
|
||
| `--nv-glow-` | `sm md lg` (accent halos) · `blur-sm/md/lg` `spread-sm/md/lg` (geometry for a tinted glow) · `strength` (how much tint a glow carries) |
|
||
|
||
### Motion
|
||
|
||
| Family | Steps |
|
||
| --- | --- |
|
||
| `--nv-duration-` | `instant fast quick normal slow slower travel expand theme shimmer` |
|
||
| `--nv-ease-` | `standard entrance exit spring emphasized linear` |
|
||
| `--nv-transition-` | `colors depth control surface expand` (composites) |
|
||
| displacement | `--nv-lift-hover` `--nv-press-depth` `--nv-travel-sm/md/lg` |
|
||
| sequence | `--nv-stagger` — the gap between siblings arriving one after another |
|
||
|
||
`prefers-reduced-motion` collapses every duration and displacement at the token
|
||
level. Components never opt in individually.
|
||
|
||
### Other
|
||
|
||
`--nv-focus-ring` · `--nv-focus-ring-width` · `--nv-border-width` ·
|
||
`--nv-border-width-strong` · `--nv-target-min` · `--nv-layout-gutter` ·
|
||
`--nv-layout-max-width` · `--nv-selection-name` · `--nv-anchor` ·
|
||
`--nv-button-offset` · `--nv-bed-tint` · `--nv-scroller-item` ·
|
||
`--nv-scroller-fade` · `--nv-content-name` · `--nv-card-tint` ·
|
||
`--nv-tile-tint` · `--nv-avatar-tint` · `--nv-pointer-x` / `--nv-pointer-y`
|
||
(set by `niveus.js`) · `--nv-reveal-index` (set by `niveus.js`)
|
||
|
||
---
|
||
|
||
## JavaScript
|
||
|
||
`niveus.js` is optional and dependency-free; it exposes `window.nv`. Without it
|
||
everything still renders — state changes simply arrive instead of travelling.
|
||
|
||
| Function | Signature | Does |
|
||
| --- | --- | --- |
|
||
| `nv.transition` | `(update, { direction, kind, scope }) => Promise` | Runs `update` inside a view transition so the change can be followed. `direction` is `"forward"`/`"backward"`; `kind: "theme"` slows the cross-fade; `scope` is the selection group (or list of groups) whose marker should travel — pass the group whose `aria-current`/`aria-selected` the update moves. Without `scope` nothing is lifted and the change cross-fades in place. Falls back to running `update` directly under reduced motion or without API support. |
|
||
| `nv.setTheme` | `("light" \| "dark" \| "system") => Promise` | Cross-fades the whole surface into the new appearance and fires `nv:theme` on `<html>`. |
|
||
| `nv.syncThemeControls` | `(theme) => void` | Sets `aria-pressed` on every `[data-nv-theme]`. |
|
||
| `nv.openDialog` | `(dialog \| id, trigger?) => dialog` | `showModal()`, plus a transform origin so the dialog expands out of its trigger. |
|
||
| `nv.selectTab` | `(tablist, tab) => Promise` | Moves selection and its panel, with direction. |
|
||
| `nv.initScroller` | `(frame) => void` | Wires one scroller's controls. |
|
||
| `nv.liftLabels` | `(scope) => Element[]` | Names the navigation items in `scope` so a travelling marker passes behind them, and returns them. `nv.transition` does this for its `scope` and removes the names afterwards. |
|
||
| `nv.wire` | `(scope = document) => void` | Applies all of the below, and starts watching `.nv-reveal` / `.nv-reveal-group`. Runs once on load; call again after injecting markup. |
|
||
| `nv.prefersReducedMotion` | `() => boolean` | |
|
||
|
||
### Data attributes
|
||
|
||
| Attribute | On | Does |
|
||
| --- | --- | --- |
|
||
| `data-theme` | `<html>` | `light` / `dark`. Absent follows the OS. |
|
||
| `data-nv-brand` | any element | Re-derives the whole color set for that subtree. |
|
||
| `data-nv-theme` | button | Sets the appearance when clicked. |
|
||
| `data-nv-dialog` | button | Opens the dialog with that id, from itself. |
|
||
| `data-nv-close` | button | Closes its dialog or popover. |
|
||
| `data-nv-tabs` | tablist | Wires `[role=tab]` children to their `aria-controls` panels, with arrow keys. |
|
||
| `data-nv-scroller` | `.nv-scroller-frame` | Wires its `[data-nv-scroll="prev"\|"next"]` controls. |
|
||
| `data-scrolled` | `.nv-nav` | Set by the application on scroll; gives the bar its shadow. |
|
||
| `data-nv-direction` | `<html>` | Set during a transition by `nv.transition`. |
|
||
| `data-nv-transition` | `<html>` | `"theme"` during an appearance change. |
|
||
| `data-nv-reveal` | revealed element | `pending` while waiting to scroll into view, `shown` while arriving; removed once it has. Set by `niveus.js`. |
|
||
| `data-nv-travelling` | selection group | Set by `nv.transition` on each `scope` for the length of the change; names its marker. |
|
||
|
||
---
|
||
|
||
## Rules that bite
|
||
|
||
1. **`view-transition-name` must be unique per document.** A duplicate makes
|
||
the browser skip the transition entirely. Markers are only named while their
|
||
group is in `scope`, so this only bites when one transition moves two groups
|
||
at once: give each its own `--nv-selection-name`. `.nv-nav-tabs` defaults
|
||
to `nv-tabs-selection` and everything else to `nv-selection`.
|
||
2. **A menu and its trigger must name the same anchor** through `--nv-anchor`,
|
||
and the value must be unique per pair.
|
||
3. **Hide inactive `.nv-tab-panel`s with `hidden`.** `nv.selectTab` relies
|
||
on it to know which panel is leaving.
|
||
4. **Never reference `--nv-palette-*` from application code.** It is raw, and
|
||
does not adapt to the appearance.
|
||
5. **A floating control positioned with `translate`** needs
|
||
`.nv-button--float` and `--nv-button-offset`, or the hover lift overwrites
|
||
its position.
|
||
6. **Icon-only buttons need `aria-label`.** The system gives them a 44px target
|
||
but cannot give them a name.
|
||
|
||
---
|
||
|
||
Made by **Nexoniarz**.
|