site: rebuilt on Niveus, and the palette stops being a copy
Niveus is the interface language the project uses from here on -- this site
first, applications after it. Rebuilding the site on it is what proves the
system is one, rather than a folder of CSS with a README.
**`style.css` is gone.** 21 KB that transcribed include/theme.h by hand:
palette, type scale, shadows, spacing, every component. The intent was right --
"a site describing an operating system should look like the operating system"
-- and the mechanism was a copy, which means two files that have to be kept in
step by remembering to. What replaced it is `app.css`, which is layout and
nothing else, and one declaration in each page:
:root { --nv-brand: #7C5CFF; }
That is SCH_ACCENT. Niveus derives the accent and its states, the link colour,
the focus ring, the tint in the greys and how far the status colours lean, for
light and dark both. One number to keep true instead of forty.
**The site is now adaptive.** Dark by default, because the OS is dark, with a
Light/Dark/Auto group in the bar that is real. The choice is kept in
localStorage and re-applied by an inline script before first paint, so the page
never renders in one appearance and corrects itself while you watch.
**PSOGM keeps its one purple, and now says so structurally.** #4B1D9A is
spelled the way Niveus spells a subtree with its own colour -- `data-nv-brand`
with its own `--nv-brand` on that section -- so every role inside re-derives
from it rather than being painted on. Still exactly one place, which is what
branding/README.md asks for.
Content is unchanged; what changed is what it is made of. Cards are `.nv-card`,
tags are `.nv-badge`, the support table is `.nv-table`, the crash section is a
`.nv-bed`, and the docs reader's two rails are `.nv-nav--vertical` with the
current document marked by `aria-current` rather than a class of our own.
`docs.js` emits `.nv-table` and `.nv-code`, so a change to the system reaches
the documentation too.
Three things were found by looking at it in a browser rather than by reading
it, and all three are the same mistake: **a `.nv-card` carries no padding of
its own -- its parts do.** The stat tiles, the "One ISO, one stick" band and
the card headers were all built from bare children, so numbers ran to the card
edge, the USB mark hung off it, and a title and its badge sat at opposite ends
of a row meant for a title and a trailing slot. Where the component had a right
way to say it, the markup now says it that way; where it did not -- a tile has
no parts -- `app.css` supplies the padding and says why.
Checked: every nv- class used across the three pages and docs.js exists in the
CSS, every token referenced by app.css is defined, and app.css contains no hex
value at all. Niveus's own tools/check.py passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9ab8a7a426
commit
6490e5c759
89 changed files with 20804 additions and 1363 deletions
393
docs/niveus/REFERENCE.md
Normal file
393
docs/niveus/REFERENCE.md
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
# 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">
|
||||
<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__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. |
|
||||
|
||||
## 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 | Carries the shared content name so panels cross-fade. |
|
||||
| `.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 | |
|
||||
|
||||
## 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.
|
||||
|
||||
## 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 content passes under. |
|
||||
| `.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.
|
||||
|
||||
## 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, kicker | 12px uppercase |
|
||||
| `.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 | |
|
||||
|
||||
## 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` | cross-fading region | Content that should cross-fade in place when it changes. |
|
||||
| `.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 elevation-tint-1 … -5
|
||||
material-frosted material-glass material-border
|
||||
focus-ring focus-ring-contrast selection
|
||||
```
|
||||
|
||||
`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}` 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` |
|
||||
| `--nv-font-` | `display heading title body label caption code` (composite shorthands) |
|
||||
| `--nv-font-family-` | `sans mono` |
|
||||
| `--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` |
|
||||
| `--nv-blur-` | `sm md lg xl` — also `backdrop-frosted` `backdrop-glass` `backdrop-scrim` |
|
||||
| `--nv-material-` | `{solid,elevated,inset,frosted,glass}-{bg,border,shadow}` |
|
||||
|
||||
### Motion
|
||||
|
||||
| Family | Steps |
|
||||
| --- | --- |
|
||||
| `--nv-duration-` | `instant fast quick normal slow slower travel expand theme` |
|
||||
| `--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` |
|
||||
|
||||
`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`
|
||||
|
||||
---
|
||||
|
||||
## 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 }) => Promise` | Runs `update` inside a view transition so the change can be followed. `direction` is `"forward"`/`"backward"`; `kind: "theme"` slows the cross-fade. 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) => void` | Names navigation items so a travelling marker passes behind them. |
|
||||
| `nv.wire` | `(scope = document) => void` | Applies all of the below. 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. |
|
||||
|
||||
---
|
||||
|
||||
## Rules that bite
|
||||
|
||||
1. **`view-transition-name` must be unique per document.** A duplicate makes
|
||||
the browser skip the transition entirely. Each selection group needs its own
|
||||
`--nv-selection-name`; `.nv-nav-tabs` defaults to `nv-tabs-selection` and
|
||||
everything else to `nv-selection`, which is enough for one of each per page.
|
||||
2. **A menu and its trigger must name the same anchor** through `--nv-anchor`,
|
||||
and the value must be unique per pair.
|
||||
3. **Only one `.nv-tab-panel` may be visible at a time** — hide the rest with
|
||||
`hidden`. They share one content name.
|
||||
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**.
|
||||
Loading…
Reference in a new issue