# Vlak guide
Vlak is a minimal design system built from paper, ink, gray, hairlines, and a 204px module. 168 components in 18 categories: actions (14), forms (28), navigation (9), feedback (13), surfaces (8), content (22), icons (1), charts (7), patterns (13), health (13), civic (5), science (10), creative (11), engineering (2), geospatial (3), robotics (3), electronics (3), microbiology (3). Version 0.4.0. Site: https://vlak.dev. Source: https://github.com/Noord-Ventures/vlak.
Three install paths share one source, so nothing drifts: the React package (precompiled StyleX plus one stylesheet), the vendored source (the shadcn model, through the Vlak CLI or the shadcn CLI), and CSS only (`rs-*` classes on plain markup).
## Install
### React package
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Button, Dialog, Field, Input } from "@noorddev/vlak-react";
```
React 18 or 19. Every component is also its own module: `import { Button } from "@noorddev/vlak-react/components/button"`. Stateful components carry `"use client"` already, so they work inside React Server Components trees without a wrapper.
### Vendor the source
```sh
npx @noorddev/vlak-cli init
npx @noorddev/vlak-cli add button dialog
```
`init` writes `styles/vlak.css`, the Inter files, a specimen `index.html`, and `vlak.json`. `add` copies the component's StyleX leaf and its dependencies into `components/vlak/`; shared helpers (`rs.ts`, `cx.ts`, `tokens.stylex.ts`) install once. Vendored leaves need a StyleX compiler (see StyleX below).
### shadcn registry
```sh
npx shadcn add https://vlak.dev/r/button.json
```
The registry at `https://vlak.dev/r/` follows the shadcn registry-item schema. `https://vlak.dev/r/index.json` lists every item; each item's `meta.vlak` carries the category, classes, snippet, example, usage, keyboard, accessibility notes, and aliases.
### CSS only
```html
```
`@noorddev/vlak/css` paints every component through `rs-*` classes and needs no JavaScript. Individual files are exported too: `@noorddev/vlak/css/tokens.css`, `@noorddev/vlak/css/components/button.css`. The class names per component are listed on each component page and in `/r/.json` under `meta.vlak.classes`.
## Theming
Set `data-theme="dark"` on the root element for the dark scheme, `data-theme="light"` to pin light. Without either, `prefers-color-scheme` applies. `color-scheme` is set with the tokens, so native controls follow. `ThemeToggle` flips the attribute and stores the choice in `localStorage` under `vlak-theme`.
There is no accent hue. Emphasis comes from weight, size, and spacing. Charts may carry one spot color through the `spot` prop, which sets `--rs-chart-spot`.
Every token is a custom property on `:root`; override them in your own stylesheet. See tokens.md for the full list with light and dark values. The tokens also ship as JSON (`@noorddev/vlak/tokens`) and as a W3C Design Tokens (DTCG) file (`@noorddev/vlak/tokens.dtcg`).
## Cascade layers and overriding
All Vlak CSS sits in cascade layers, in this order: `vlak.tokens`, `vlak.base`, `vlak.type`, `vlak.components`, `vlak.touch`, `vlak.motion`. Unlayered author CSS wins over any of it, so overrides never need `!important`:
```css
.rs-btn-primary { border-radius: 8px; }
```
To override from inside a layer, declare yours after Vlak's: `@layer vlak.motion, app;`.
## StyleX
The leaves are StyleX. Consumers of `@noorddev/vlak-react` need no compiler: the package is precompiled and `@noorddev/vlak-react/css` carries the output. To write your own leaves against Vlak tokens, or to compile vendored leaves, use the token file:
```tsx
import * as stylex from "@stylexjs/stylex";
import { vlak, mq } from "@noorddev/vlak-react/tokens.stylex";
const styles = stylex.create({
panel: { borderTop: `1px solid ${vlak.divider}`, padding: vlak.pad, [mq.phone]: { padding: 12 } },
});
```
`vlak` aliases the CSS custom properties (`vlak.ink` is `var(--text)`), so compiled leaves and `rs-*` CSS read the same values. A StyleX compiler must include `@noorddev/vlak-react/tokens.stylex` in its compile so the variable hashes match: Vite uses `@stylexjs/unplugin`; Next.js uses `@stylexjs/postcss-plugin` plus a Babel pass with `@stylexjs/babel-plugin`. Without a compiler, import the package and its stylesheet and skip StyleX entirely.
## Components
Every component applies its styles through `rs([...classes], styles.leaf)`: the same element carries the semantic `rs-*` class (the CSS-only contract) and the compiled StyleX class. Overriding the class works on both paths.
Conventions that hold across the catalogue:
- Performance: a frame has 8.3ms at 120Hz or 16.7ms at 60Hz. User feedback lands within 100ms. Snappy transitions take 200–300ms; deliberate transitions take 300–500ms. At 1s, show progress without stealing focus. Before 10s, explain the wait and preserve the user's place.
- Accessibility: interactive targets are at least 44px by 44px. Ordinary text is at least 4.5:1 against its ground; large text and control boundaries are at least 3:1.
- Reading: body copy stays between 45 and 90 characters per line, with 66 characters as the default measure. Body line-height stays between 1.2 and 1.45 times its font size; Vlak defaults to 1.45.
- Controlled and uncontrolled: `value` / `defaultValue` / `onValueChange` (Select, Combobox, Tabs, RadioGroup, ToggleGroup, Slider, Calendar, DatePicker); `checked` / `defaultChecked` / `onCheckedChange` (Switch); `pressed` / `defaultPressed` / `onPressedChange` (Toggle); `open` / `onClose` (Dialog, AlertDialog, Sheet, Drawer, CommandDialog). Checkbox and Radio are native inputs and use `checked` / `onChange`.
- `className` and `style` merge with the component's own; native attributes and event handlers pass through to the root element (the props tables say which attribute set each component extends).
- Refs: 241 of 242 exported components forward `ref` to their root element; each props table names the element (`ref` in props.json). The rest render a plain element and take no ref.
- Names: components that render no visible label take `aria-label` or `aria-labelledby` (Select, Combobox, Switch, Slider, ButtonGroup, ToggleGroup, RadioGroup, ScrollArea, Carousel, Split). Dialogs are named by their Title part.
- Platform first: `
}]} />
```
## Props
### MasterDetail
List/detail selection with a mobile back path and preserved item focus.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` (required) | `MasterDetailItem[]` | | |
| `label` | `string` | `"Items"` | |
| `value` | `string \| null` | | |
| `defaultValue` | `string \| null` | `null` | |
| `onValueChange` | `(id: string \| null) => void` | | |
| `emptyLabel` | `string` | `"Select an item to see its details"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Select an item with its button; focus moves to the detail heading. Mobile Back restores focus to its list item. |
## Accessibility
- Native selected buttons and a named detail region. Mobile layout preserves an explicit return path.
## Classes
`rs-master-detail`, `rs-master-detail-list`, `rs-master-detail-list-hidden`, `rs-master-detail-panel`, `rs-master-detail-panel-hidden`, `rs-master-detail-title`, `rs-master-detail-description`, `rs-master-detail-back`, `rs-master-detail-button`, `rs-master-detail-selected`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md).
React: `packages/react/src/components/master-detail.tsx`
CSS: `packages/core/css/components/master-detail.css`
---
# Property grid
Aligns editable labels, values, units, and hints in an inspector.
Category: patterns
Name: `property-grid`
Also known as: PropertyGrid
Page: https://vlak.dev/components/property-grid/
## When to use
- Inspector panels and dense settings with mixed field types.
## When not to
- Read-only facts; use DescriptionList.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { PropertyGrid } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add property-grid
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/property-grid.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { PropertyGrid } from "@noorddev/vlak-react";
```
## Props
### PropertyGrid
Editable property rows with shared label/value/unit alignment.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `fields` (required) | `PropertyField[]` | | |
| `value` | `PropertyValues` | | |
| `defaultValue` | `PropertyValues` | `{}` | |
| `onValueChange` | `(values: PropertyValues) => void` | | |
| `label` | `string` | `"Properties"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, native field keys, Space | Native text/number/select fields keep their editing keys; Space toggles a switch. |
## Accessibility
- Each row labels its actual control and associates its hint. Native numeric constraints remain available to forms.
## Classes
`rs-property-grid`, `rs-property-grid-row`, `rs-property-grid-label`, `rs-property-grid-control`, `rs-property-grid-note`
## Dependencies
Registry dependencies: [input](input.md), [native-select](native-select.md), [switch](switch.md).
React: `packages/react/src/components/property-grid.tsx`
CSS: `packages/core/css/components/property-grid.css`
---
# Number field
Edits a numeric value with native validation, units, and bounded 44px increase and decrease actions.
Category: forms
Name: `number-field`
Also known as: NumberField, Number input, Numeric stepper, Quantity field
Page: https://vlak.dev/components/number-field/
## When to use
- Numeric quantities that need visible stepping, native bounds, or a unit.
- Stacked controls when increase belongs above decrease at the end of a reading.
## When not to
- A continuous interval with two endpoints; use RangeSlider.
- Codes and identifiers, which may have leading zeroes; use Input.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { NumberField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add number-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/number-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
°C
```
## Example
```tsx
import { NumberField } from "@noorddev/vlak-react";
```
## Props
### NumberField
Numeric input with native validation and bounded increment/decrement actions.
Extends `Omit, "type" | "value" | "defaultValue" | "onChange" | "size" | "min" | "max" | "step">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number \| null` | | |
| `defaultValue` | `number \| null` | `null` | |
| `onValueChange` | `(value: number \| null) => void` | | |
| `min` | `number` | | |
| `max` | `number` | | |
| `step` | `number` | `1` | |
| `label` | `ReactNode` | | |
| `unit` | `string` | | |
| `incrementLabel` | `string` | `"Increase value"` | |
| `decrementLabel` | `string` | `"Decrease value"` | |
| `controlsPlacement` | `"inline" \| "stacked"` | `"inline"` | Stack the increase button above decrease at the end of the field. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between the number field and available step actions. |
| Arrow up, Arrow down | Uses the browser's native numeric stepping while the input is focused. |
| Enter, Space | Activates a focused increase or decrease button. |
## Accessibility
- The forwarded ref reaches the native number input; label, native form attributes, and name reach that input.
- min, max, and step use native validity. The buttons clamp at bounds; typed values retain native validation feedback.
- A cleared field reports null. value/defaultValue/onValueChange support controlled and uncontrolled use; form reset restores uncontrolled defaults.
- The unit is linked as a description. Each step action has a name and a 44px target.
## Classes
`rs-number-field`, `rs-number-field-label`, `rs-number-field-row`, `rs-number-field-input`, `rs-number-field-unit`, `rs-number-field-action`, `rs-number-field-controls`, `rs-number-field-controls-stacked`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md).
React: `packages/react/src/components/number-field.tsx`
CSS: `packages/core/css/components/number-field.css`
---
# Range slider
Sets an ordered numeric interval with two named native range controls and visible endpoint values.
Category: forms
Name: `range-slider`
Also known as: RangeSlider, Interval selector, Min max slider, Dual range
Page: https://vlak.dev/components/range-slider/
## When to use
- A numeric lower and upper bound such as budget or duration.
- Separate labeled tracks when each endpoint needs clear keyboard and touch access.
## When not to
- A single setting; use Slider.
- Time-based seeking with buffered media; use MediaScrubber.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { RangeSlider } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add range-slider
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/range-slider.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { RangeSlider } from "@noorddev/vlak-react";
`€${value}`} />
```
## Props
### RangeSlider
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `[number, number]` | | |
| `defaultValue` | `[number, number]` | | |
| `onValueChange` | `(value: [number, number]) => void` | | |
| `min` | `number` | `0` | |
| `max` | `number` | `100` | |
| `step` | `number` | `1` | |
| `label` | `ReactNode` | `"Range"` | |
| `lowerLabel` | `string` | `"From"` | |
| `upperLabel` | `string` | `"To"` | |
| `name` | `string` | | |
| `disabled` | `boolean` | | |
| `formatValue` | `(value: number) => string` | `String` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between the lower and upper native range inputs. |
| Arrow keys, Home, End | Uses the browser's native range stepping within the other endpoint's bounds. |
## Accessibility
- Uses a fieldset and legend with a separate label and visible output for each endpoint; each input has a 44px-high target.
- Each endpoint's native min/max prevents crossing. formatValue also supplies aria-valuetext.
- With name, native form values are submitted as name[0] and name[1]. Uncontrolled values reset with the form.
- The ref reaches the fieldset; Field hint and error descriptions reach the group.
## Classes
`rs-range-slider`, `rs-range-slider-legend`, `rs-range-slider-row`, `rs-range-slider-label`, `rs-range-slider-input`, `rs-range-slider-output`
## Dependencies
Registry dependencies: [field](field.md).
React: `packages/react/src/components/range-slider.tsx`
CSS: `packages/core/css/components/range-slider.css`
---
# Multi-select
Selects multiple predefined options from a searchable native disclosure with named checkboxes.
Category: forms
Name: `multi-select`
Also known as: MultiSelect, Multiple select, Checkbox picker
Page: https://vlak.dev/components/multi-select/
## When to use
- Multiple values from a known option set.
- A compact summary that expands to filterable checkbox choices.
## When not to
- Freeform values; use TagInput.
- One option only; use Select or NativeSelect.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { MultiSelect } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add multi-select
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/multi-select.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { MultiSelect } from "@noorddev/vlak-react";
```
## Props
### MultiSelect
A native disclosure containing named checkboxes; selections remain visible when collapsed.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` (required) | `MultiSelectOption[]` | | |
| `value` | `string[]` | | |
| `defaultValue` | `string[]` | `[]` | |
| `onValueChange` | `(value: string[]) => void` | | |
| `label` | `ReactNode` | `"Options"` | |
| `placeholder` | `string` | `"Select options"` | |
| `searchable` | `boolean` | `true` | |
| `searchLabel` | `string` | `"Filter options"` | |
| `emptyLabel` | `ReactNode` | `"No matching options"` | |
| `clearLabel` | `string` | `"Clear selection"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Enter, Space | Opens or closes the native summary, or toggles the focused checkbox. |
| Tab | Moves through search, available checkboxes, and clear selection. |
| Escape | Closes the disclosure and returns focus to its summary. |
## Accessibility
- Uses native details and checkboxes instead of exposing an incomplete listbox interaction.
- The legend names the field; each checkbox has its own visible name. Selected rows change fill across the full surface.
- Disabled options cannot change; clear preserves disabled selections. Empty search results are announced politely.
- With name, selected values are submitted as repeated fields. The ref reaches the fieldset; uncontrolled selections reset with the form.
## Classes
`rs-multi-select`, `rs-multi-select-legend`, `rs-multi-select-trigger`, `rs-multi-select-panel`, `rs-multi-select-options`, `rs-multi-select-option`, `rs-multi-select-selected`, `rs-multi-select-empty`, `rs-multi-select-clear`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md), [checkbox](checkbox.md), [icons](icons.md), [field](field.md).
React: `packages/react/src/components/multi-select.tsx`
CSS: `packages/core/css/components/multi-select.css`
---
# Tag input
Creates and removes freeform text tokens with paste splitting, duplicate prevention, and validation.
Category: forms
Name: `tag-input`
Also known as: TagInput, Token input, Chips input, Freeform tags
Page: https://vlak.dev/components/tag-input/
## When to use
- Short freeform labels, recipients, or keywords.
- Comma-separated or newline-separated pasted values that should become distinct tokens.
## When not to
- A fixed vocabulary; use MultiSelect.
- Long prose; use Textarea.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { TagInput } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add tag-input
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/tag-input.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Design
```
## Example
```tsx
import { TagInput } from "@noorddev/vlak-react";
tag.length > 24 ? "Use 24 characters or fewer" : undefined} />
```
## Props
### TagInput
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string[]` | | |
| `defaultValue` | `string[]` | `[]` | |
| `onValueChange` | `(value: string[]) => void` | | |
| `label` | `ReactNode` | `"Tags"` | |
| `name` | `string` | | |
| `disabled` | `boolean` | | |
| `placeholder` | `string` | `"Add a tag"` | |
| `maxTags` | `number` | | |
| `validate` | `(tag: string) => string` | | Return an error for an invalid token, or undefined to accept it. |
| `addLabel` | `string` | `"Add"` | |
| `removeLabel` | `(tag: string) => string` | `(tag) => \`Remove ${tag}\`` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Enter, comma | Commits a trimmed draft as a tag without submitting the form. |
| Backspace in an empty input | Focuses the last tag's remove button. |
| Escape | Clears the current draft and its error. |
| Tab, Enter, Space | Reaches and activates named Add and Remove buttons. |
## Accessibility
- The forwarded ref reaches the text input. Each 44px remove target is named with its tag.
- Exact duplicate tags are ignored; validate and maxTags reject an addition while preserving the draft and exposing an alert.
- Hidden fields submit each tag under name. Form reset restores uncontrolled tags and clears the draft.
- Keyboard composition is respected; Enter does not commit while an input method is composing text.
## Classes
`rs-tag-input`, `rs-tag-input-label`, `rs-tag-input-list`, `rs-tag-input-tag`, `rs-tag-input-remove`, `rs-tag-input-row`, `rs-tag-input-input`, `rs-tag-input-add`, `rs-tag-input-feedback`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md), [icons](icons.md), [field](field.md).
React: `packages/react/src/components/tag-input.tsx`
CSS: `packages/core/css/components/tag-input.css`
---
# Date range picker
Collects start and end dates with two native date editors, shared constraints, and 44px controls.
Category: forms
Name: `date-range-picker`
Also known as: DateRangePicker, Date interval, Start and end dates
Page: https://vlak.dev/components/date-range-picker/
## When to use
- A start/end date range that should use the platform's date editor and calendar picker.
- Forms that submit ISO calendar dates without time-zone conversion.
## When not to
- A single date; use DatePicker or Calendar.
- Time-of-day selection; use TimeField.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { DateRangePicker } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add date-range-picker
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/date-range-picker.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { DateRangePicker } from "@noorddev/vlak-react";
```
## Props
### DateRangePicker
Two native date editors share bounds; changing the start beyond the end clears the end.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `DateRangeValue` | | ISO calendar dates, YYYY-MM-DD; no time zone conversion. |
| `defaultValue` | `DateRangeValue` | `{ start: "", end: "" }` | |
| `onValueChange` | `(value: DateRangeValue) => void` | | |
| `label` | `ReactNode` | `"Date range"` | |
| `startLabel` | `string` | `"Start date"` | |
| `endLabel` | `string` | `"End date"` | |
| `min` | `string` | | |
| `max` | `string` | | |
| `required` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the two native date editors and their platform picker controls. |
| Arrow keys | Edits the active date segment according to the browser's native behavior. |
## Accessibility
- Uses a fieldset/legend and a separately labeled native date input for each endpoint. The browser owns each date popup.
- Values use year-month-day strings, for example 2026-09-06. A new start after the old end clears the end; end's minimum follows the start.
- min, max, and required use native constraint validation. A supplied inverted controlled range is marked invalid.
- With name, form fields are name[start] and name[end]. The ref reaches the fieldset; uncontrolled values reset with the form.
## Classes
`rs-date-range-picker`, `rs-date-range-picker-legend`, `rs-date-range-picker-fields`, `rs-date-range-picker-input`
## Dependencies
Registry dependencies: [input](input.md), [field](field.md).
React: `packages/react/src/components/date-range-picker.tsx`
CSS: `packages/core/css/components/date-range-picker.css`
---
# Time field
Edits a time using the platform's localized time control with native bounds and second-based steps.
Category: forms
Name: `time-field`
Also known as: TimeField, Time input, Time picker
Page: https://vlak.dev/components/time-field/
## When to use
- A time of day with browser-native locale and keyboard behavior.
- Minutes or seconds, with the native step measured in seconds.
## When not to
- An elapsed duration; use NumberField with units.
- A calendar date; use DatePicker.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { TimeField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add time-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/time-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { TimeField } from "@noorddev/vlak-react";
```
## Props
### TimeField
The platform time editor, including its locale, keyboard and step validation.
Extends `Omit, "type" | "value" | "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | | A 24-hour HTML time value, HH:mm or HH:mm:ss. The browser localizes editing. |
| `defaultValue` | `string` | `""` | |
| `onValueChange` | `(value: string) => void` | | |
| `label` | `ReactNode` | | |
| `hint` | `ReactNode` | | |
| `error` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, arrow keys | Uses the browser's time segment navigation and native stepping. |
| Typing | Edits the active hour, minute, or second segment according to the platform. |
## Accessibility
- Wraps Input, preserving label, hint, error, native form attributes, disabled/readOnly and the forwarded input ref.
- Values use HH:mm or HH:mm:ss; the visible editor follows the browser's locale and 12/24-hour preference.
- No date or time-zone conversion is performed. Controlled/uncontrolled state and form reset are supported.
## Classes
`rs-time-field`
## Dependencies
Registry dependencies: [input](input.md).
React: `packages/react/src/components/time-field.tsx`
CSS: `packages/core/css/components/time-field.css`
---
# File upload
Collects validated files through browse or drop, with optional upload progress, cancellation, and retry.
Category: forms
Name: `file-upload`
Also known as: FileUpload, Drop zone, Attachment upload, File input
Page: https://vlak.dev/components/file-upload/
## When to use
- Validated attachment queues with native file browsing and drag-and-drop.
- Provide onUpload when the app has a transport; it receives an AbortSignal and progress callback.
## When not to
- Assuming files upload automatically; without onUpload this only collects selected files.
- Client checks as security enforcement; validate uploaded files again on the server.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { FileUpload } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add file-upload
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/file-upload.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Choose filesDrop files here or browse
```
## Example
```tsx
import { FileUpload } from "@noorddev/vlak-react";
```
## Props
### FileUpload
Validated file selection, with an optional cancellable upload transport.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `File[]` | | |
| `defaultValue` | `File[]` | `[]` | |
| `onValueChange` | `(files: File[]) => void` | | |
| `accept` | `string` | | |
| `multiple` | `boolean` | `true` | |
| `maxFiles` | `number` | | |
| `maxSize` | `number` | | |
| `disabled` | `boolean` | | |
| `name` | `string` | | |
| `label` | `string` | `"Choose files"` | |
| `description` | `ReactNode` | `"Drop files here or browse"` | |
| `onReject` | `(rejections: FileUploadRejection[]) => void` | | |
| `onUpload` | `(file: File, context: FileUploadContext) => Promise` | | Optional transport supplied by the app. Omit to collect files without uploading. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Reaches the native file picker and labeled Remove, Cancel, and Retry actions. |
## Accessibility
- The native file input covers the drop target, remains keyboard-focusable, and receives the forwarded ref.
- Rejected types, sizes and counts produce readable errors. Upload status is announced; progress bars are named with the file.
- The app supplies onUpload(file, { signal, onProgress }). Cancel aborts the signal; errors retain the file and expose Retry.
- With name, the browser's formdata event appends the accepted queue to native FormData. Use multipart/form-data for native file submission. Disabled queues are omitted.
- Form reset restores uncontrolled files, clears errors and aborts active uploads. Unmount aborts outstanding transports.
## Classes
`rs-file-upload`, `rs-file-upload-drop`, `rs-file-upload-drag`, `rs-file-upload-input`, `rs-file-upload-title`, `rs-file-upload-description`, `rs-file-upload-list`, `rs-file-upload-item`, `rs-file-upload-row`, `rs-file-upload-name`, `rs-file-upload-actions`, `rs-file-upload-action`, `rs-file-upload-status`
## Dependencies
Registry dependencies: [button](button.md), [progress](progress.md).
React: `packages/react/src/components/file-upload.tsx`
CSS: `packages/core/css/components/file-upload.css`
---
# Transfer list
Assigns options between available and selected lists using native checkboxes and explicit move actions.
Category: forms
Name: `transfer-list`
Also known as: TransferList, Dual listbox, Assignment lists
Page: https://vlak.dev/components/transfer-list/
## When to use
- Assigning a visible subset from a manageable option list.
- Work where available and assigned options should stay visible together.
## When not to
- Very large lists; use searchable MultiSelect.
- Ordering selected records; use SortableList.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { TransferList } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add transfer-list
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/transfer-list.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { TransferList } from "@noorddev/vlak-react";
```
## Props
### TransferList
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `options` (required) | `TransferListOption[]` | | |
| `value` | `string[]` | | |
| `defaultValue` | `string[]` | `[]` | |
| `onValueChange` | `(value: string[]) => void` | | |
| `label` | `ReactNode` | `"Assign options"` | |
| `availableLabel` | `string` | `"Available"` | |
| `selectedLabel` | `string` | `"Selected"` | |
| `addLabel` | `string` | `"Add selected"` | |
| `removeLabel` | `string` | `"Remove selected"` | |
| `emptyLabel` | `string` | `"No options"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Space | Moves through and marks native checkbox options. |
| Enter, Space on a move action | Adds or removes the marked options; marked state clears after the move. |
## Accessibility
- A top-level fieldset names the task; available and selected lists have distinct legends and counts.
- Every option and move action has a 44px target. Disabled options stay fixed; unavailable moves are disabled.
- The selected count is a polite status. Hidden fields submit each selected value under name.
- The ref reaches the fieldset. Form reset restores uncontrolled values and clears marked options.
## Classes
`rs-transfer-list`, `rs-transfer-list-legend`, `rs-transfer-list-columns`, `rs-transfer-list-panel`, `rs-transfer-list-heading`, `rs-transfer-list-options`, `rs-transfer-list-item`, `rs-transfer-list-actions`, `rs-transfer-list-action`, `rs-transfer-list-empty`, `rs-transfer-list-status`
## Dependencies
Registry dependencies: [checkbox](checkbox.md), [button](button.md).
React: `packages/react/src/components/transfer-list.tsx`
CSS: `packages/core/css/components/transfer-list.css`
---
# Inline edit
Switches a text value into an editor with explicit save and cancel, validation, and optional async persistence.
Category: forms
Name: `inline-edit`
Also known as: InlineEdit, Editable text, Click to edit
Page: https://vlak.dev/components/inline-edit/
## When to use
- A short text value edited in its reading context.
- Provide onSave to await persistence before committing a new value.
## When not to
- Long-form writing; use Textarea.
- Implicit save-on-blur flows; this requires an explicit save.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { InlineEdit } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add inline-edit
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/inline-edit.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Project name
Field study
```
## Example
```tsx
import { InlineEdit } from "@noorddev/vlak-react";
value.trim() ? undefined : "Enter a project name"} />
```
## Props
### InlineEdit
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | | |
| `defaultValue` | `string` | `""` | |
| `onValueChange` | `(value: string) => void` | | |
| `label` | `string` | `"Value"` | |
| `name` | `string` | | |
| `disabled` | `boolean` | | |
| `placeholder` | `string` | `"Not set"` | |
| `validate` | `(value: string) => string` | | |
| `onSave` | `(value: string) => void \| Promise` | | Resolves before the value is committed. Rejections leave the draft editable. |
| `editLabel` | `string` | `"Edit"` | |
| `saveLabel` | `string` | `"Save"` | |
| `cancelLabel` | `string` | `"Cancel"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Enter, Space on Edit | Opens the editor, focuses the input and selects its text. |
| Enter in the editor | Validates and saves without submitting the enclosing form. |
| Escape in the editor | Discards the draft and returns focus to Edit. |
## Accessibility
- The input is named by the visible label. Save errors preserve the draft and appear as alerts.
- Successful save and cancel return focus to Edit. Pending saves disable duplicate actions and expose aria-busy.
- Hidden name submits only the committed value. Form reset restores uncontrolled defaults and discards drafts; late pending responses do not reapply them.
- The forwarded ref reaches the root div. No nested form is introduced.
## Classes
`rs-inline-edit`, `rs-inline-edit-row`, `rs-inline-edit-label`, `rs-inline-edit-value`, `rs-inline-edit-input`, `rs-inline-edit-action`, `rs-inline-edit-error`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md).
React: `packages/react/src/components/inline-edit.tsx`
CSS: `packages/core/css/components/inline-edit.css`
---
# Rating
Collects a discrete numeric score with 44px native radio choices and an optional clear action.
Category: forms
Name: `rating`
Also known as: Rating, Score input, Rating group
Page: https://vlak.dev/components/rating/
## When to use
- An explicit score on a short, ordered scale.
- Clearable feedback where no rating is distinct from the lowest score.
## When not to
- Unordered choices; use Radio.
- Large or continuous numeric ranges; use Slider or NumberField.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Rating } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add rating
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/rating.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { Rating } from "@noorddev/vlak-react";
`${value} out of ${max}`} />
```
## Props
### Rating
A discrete score using native radios; zero means no rating.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `number` | | |
| `defaultValue` | `number` | `0` | |
| `onValueChange` | `(value: number) => void` | | |
| `max` | `number` | `5` | |
| `label` | `ReactNode` | `"Rating"` | |
| `getLabel` | `(value: number, max: number) => string` | `(score, total) => \`${score} of ${total}\`` | |
| `clearable` | `boolean` | `true` | |
| `clearLabel` | `string` | `"Clear rating"` | |
| `required` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Enters the native radio group at its current choice and reaches Clear. |
| Arrow keys | Moves and selects among the native radio choices. |
| Space | Selects a focused radio or activates Clear. |
## Accessibility
- The fieldset legend names the score; getLabel gives each choice a complete name such as 3 of 5.
- Selection changes the full choice surface. Each choice is 44px with a 4px corner and a visible focus outline.
- Zero means no rating. max is limited to 1–10 whole choices. required uses native radio-group validation.
- name submits the selected score. The ref reaches the fieldset; uncontrolled values reset with the form.
## Classes
`rs-rating`, `rs-rating-legend`, `rs-rating-choices`, `rs-rating-choice`, `rs-rating-selected`, `rs-rating-input`, `rs-rating-clear`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/rating.tsx`
CSS: `packages/core/css/components/rating.css`
---
# Playback controls
Groups named play, pause, previous, next, and stop controls with 44px targets.
Category: actions
Name: `playback-controls`
Also known as: PlaybackControls, Transport controls, Media controls
Page: https://vlak.dev/components/playback-controls/
## When to use
- Transport controls beside media metadata or inside a player.
- Custom previous and next labels when actions restart or seek.
## When not to
- A media source by itself; use MediaPlayer to bind to audio or video.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { PlaybackControls } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add playback-controls
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/playback-controls.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { PlaybackControls } from "@noorddev/vlak-react";
```
## Props
### PlaybackControls
Named, keyboard-operable transport buttons. Playback state may be owned by a media element.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `playing` | `boolean` | | |
| `defaultPlaying` | `boolean` | `false` | |
| `onPlayingChange` | `(playing: boolean) => void` | | |
| `onPrevious` | `() => void` | | |
| `onNext` | `() => void` | | |
| `onStop` | `() => void` | | |
| `disabled` | `boolean` | `false` | |
| `previousDisabled` | `boolean` | `false` | |
| `nextDisabled` | `boolean` | `false` | |
| `previousLabel` | `string` | `"Previous track"` | |
| `nextLabel` | `string` | `"Next track"` | |
| `label` | `string` | `"Playback controls"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Shift+Tab | Moves between enabled transport buttons. |
| Enter, Space | Activates the focused transport action. |
## Accessibility
- Every icon button has a state-aware accessible name.
- Optional previous, next, and stop actions render only when supplied.
- The containing group has a customisable label; disabled actions use native disabled buttons.
## Classes
`rs-playback-controls`, `rs-playback-action`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md).
React: `packages/react/src/components/playback-controls.tsx`
CSS: `packages/core/css/components/playback-controls.css`
---
# Media scrubber
Seeks through media in seconds with elapsed time, buffering, chapters, and optional previews.
Category: forms
Name: `media-scrubber`
Also known as: MediaScrubber, Seek bar, Media timeline
Page: https://vlak.dev/components/media-scrubber/
## When to use
- A media timeline where values are seconds.
- Chapter navigation or supplied thumbnail previews.
## When not to
- An arbitrary numeric setting; use Slider.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { formatMediaTime, MediaScrubber } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add media-scrubber
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/media-scrubber.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
0:424:00
```
## Example
```tsx
import { MediaScrubber } from "@noorddev/vlak-react";
```
## Props
### MediaScrubber
A native range in seconds with elapsed and total time. The input remains a 44px target.
Extends `Omit, "type" | "value" | "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `duration` (required) | `number` | | |
| `label` | `string` | `"Playback position"` | |
| `showTime` | `boolean` | `true` | |
| `buffered` | `number` | `0` | Last buffered second. |
| `chapters` | `readonly MediaChapter[]` | `[]` | |
| `preview` | `(seconds: number) => ReactNode` | | Thumbnail or other visual preview for the pointed or focused second. |
| `value` | `number` | | |
| `defaultValue` | `number` | `0` | |
| `step` | `number` | `1` | |
| `onValueChange` | `(value: number) => void` | | |
### Functions
- `formatMediaTime` (function): Elapsed media time, including hours when needed. Invalid duration is displayed as zero.
## Keyboard
| Keys | Does |
| --- | --- |
| Arrow keys, Home, End | Uses the native range input to seek within the duration. |
| Tab | Moves to the optional native chapter selector; selecting a chapter seeks to its start. |
## Accessibility
- The range announces elapsed and total time with aria-valuetext.
- Unknown or invalid duration disables seeking.
- Previews are visual supplements; the native range supplies the equivalent position text.
## Classes
`rs-media-scrubber`, `rs-media-scrubber-times`, `rs-media-scrubber-track`, `rs-media-scrubber-rail`, `rs-media-scrubber-buffered`, `rs-media-scrubber-slider`, `rs-media-scrubber-preview`, `rs-media-scrubber-chapters`
## Dependencies
Registry dependencies: [slider](slider.md), [native-select](native-select.md).
React: `packages/react/src/components/media-scrubber.tsx`
CSS: `packages/core/css/components/media-scrubber.css`
---
# Media player
Connects native audio or video to playback, seeking, captions, speed, volume, and full screen.
Category: patterns
Name: `media-player`
Also known as: MediaPlayer, Audio player, Video player
Page: https://vlak.dev/components/media-player/
## When to use
- Playing an actual audio or video source with consistent controls.
- Media with captions and a supplied text transcript.
## When not to
- DRM, adaptive streaming protocols, or a video editing timeline.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { MediaPlayer } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add media-player
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/media-player.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Film
```
## Example
```tsx
import { MediaPlayer } from "@noorddev/vlak-react";
A text transcript of the film.} />
```
## Props
### MediaPlayer
Native media with Vlak transport, seeking, volume, captions, and recoverable loading errors.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLMediaElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `src` (required) | `string` | | |
| `title` (required) | `string` | | |
| `kind` | `"audio" \| "video"` | `"video"` | |
| `poster` | `string` | | |
| `preload` | `"none" \| "metadata" \| "auto"` | `"metadata"` | |
| `tracks` | `readonly MediaTrack[]` | `[]` | |
| `transcript` | `ReactNode` | | |
| `onPlayingChange` | `(playing: boolean) => void` | | |
| `onTimeChange` | `(seconds: number) => void` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Shift+Tab | Moves through transport, seeking, volume, speed, captions, and available full-screen actions. |
| Enter, Space | Activates buttons; range and select controls retain native keyboard behavior. |
| Escape | Exits browser full screen. |
## Accessibility
- Native controls remain available before hydration.
- Supply caption tracks for spoken video and a transcript where appropriate.
- Load and play failures are announced; retry preserves access to the player.
- Full screen is shown only when the browser supplies the API.
## Classes
`rs-media-player`, `rs-media-player-media`, `rs-media-player-title`, `rs-media-player-controls`, `rs-media-player-action`, `rs-media-player-volume`, `rs-media-player-status`, `rs-media-player-transcript`, `rs-media-player-summary`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md), [slider](slider.md), [native-select](native-select.md), [playback-controls](playback-controls.md), [media-scrubber](media-scrubber.md).
React: `packages/react/src/components/media-player.tsx`
CSS: `packages/core/css/components/media-player.css`
---
# Waveform
Displays supplied audio amplitudes with optional seeking and editable selection bounds.
Category: content
Name: `waveform`
Also known as: Waveform, Audio waveform, Audio region
Page: https://vlak.dev/components/waveform/
## When to use
- A supplied waveform for an audio recording.
- Seeking or selecting an interval in normalised zero-to-one coordinates.
## When not to
- Generating or decoding audio data; provide amplitude samples.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Waveform } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add waveform
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/waveform.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { Waveform } from "@noorddev/vlak-react";
```
## Props
### Waveform
A waveform from supplied amplitude data, optionally scrubbed through a native range.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `samples` (required) | `readonly number[]` | | Amplitudes from zero to one; values are clamped. |
| `label` (required) | `string` | | |
| `value` | `number` | | |
| `defaultValue` | `number` | `0` | |
| `onValueChange` | `(position: number) => void` | | |
| `disabled` | `boolean` | `false` | |
| `region` | `WaveformRegion` | | |
| `defaultRegion` | `WaveformRegion` | `{ start: 0, end: 1 }` | |
| `onRegionChange` | `(region: WaveformRegion) => void` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Arrow keys, Home, End | Operates the native seek range and optional selection start and end ranges. |
## Accessibility
- Static waveforms have a labelled image role.
- Interactive waveforms announce percentage and selection endpoints.
- Long inputs are reduced to no more than 240 peak bars to bound SVG rendering cost.
## Classes
`rs-waveform`, `rs-waveform-stage`, `rs-waveform-plot`, `rs-waveform-input`, `rs-waveform-region`, `rs-waveform-region-controls`, `rs-waveform-label`, `rs-waveform-bar`, `rs-waveform-played`
## Dependencies
Registry dependencies: [slider](slider.md).
React: `packages/react/src/components/waveform.tsx`
CSS: `packages/core/css/components/waveform.css`
---
# Image viewer
Inspects an image collection with zoom, navigation, and a native dialog lightbox.
Category: patterns
Name: `image-viewer`
Also known as: ImageViewer, Lightbox, Image gallery
Page: https://vlak.dev/components/image-viewer/
## When to use
- Examining a finite collection of labelled images.
- Inline preview with an optional focused lightbox.
## When not to
- Editing pixels or drawing annotations; use an image editor.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ImageViewer } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add image-viewer
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/image-viewer.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Image caption
```
## Example
```tsx
import { ImageViewer } from "@noorddev/vlak-react";
```
## Props
### ImageViewer
Inspect a labelled image collection inline or in a native lightbox.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `images` (required) | `readonly ViewerImage[]` | | |
| `value` | `number` | | |
| `defaultValue` | `number` | `0` | |
| `onValueChange` | `(index: number) => void` | | |
| `label` | `string` | `"Image viewer"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Arrow left, Arrow right | Changes images when the image canvas is focused. |
| Tab, Enter, Space | Operates image navigation and zoom controls. |
| Escape | Closes the native lightbox and returns focus to its opener. |
## Accessibility
- Each image requires alt text.
- Native dialog supplies modal focus behavior; visible errors replace broken image output.
- Navigation buttons disable at collection boundaries.
## Classes
`rs-image-viewer`, `rs-image-viewer-canvas`, `rs-image-viewer-plane`, `rs-image-viewer-image`, `rs-image-viewer-controls`, `rs-image-viewer-navigation`, `rs-image-viewer-action`, `rs-image-viewer-caption`, `rs-image-viewer-modal`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md), [canvas-controls](canvas-controls.md), [dialog](dialog.md).
React: `packages/react/src/components/image-viewer.tsx`
CSS: `packages/core/css/components/image-viewer.css`
---
# Canvas controls
Adjusts bounded zoom and exposes fit and reset actions for a canvas.
Category: actions
Name: `canvas-controls`
Also known as: CanvasControls, Zoom controls, Viewport controls
Page: https://vlak.dev/components/canvas-controls/
## When to use
- A canvas, diagram, map, or image with application-owned transforms.
## When not to
- Rendering or panning the canvas; these controls emit zoom and action callbacks.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CanvasControls } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add canvas-controls
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/canvas-controls.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { CanvasControls } from "@noorddev/vlak-react";
```
## Props
### CanvasControls
Zoom, fit, and reset actions for a canvas. The canvas owns pan and rendering.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `zoom` | `number` | | |
| `defaultZoom` | `number` | `1` | |
| `onZoomChange` | `(zoom: number) => void` | | |
| `minZoom` | `number` | `0.25` | |
| `maxZoom` | `number` | `4` | |
| `step` | `number` | `0.25` | |
| `onFit` | `() => void` | | |
| `onReset` | `() => void` | | |
| `disabled` | `boolean` | `false` | |
| `label` | `string` | `"Canvas controls"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Operates zoom, optional fit, and reset buttons. |
## Accessibility
- Zoom has a visible numeric reading.
- Limits disable the corresponding zoom action.
- All actions keep at least a 44px target.
## Classes
`rs-canvas-controls`, `rs-canvas-action`, `rs-canvas-zoom`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md).
React: `packages/react/src/components/canvas-controls.tsx`
CSS: `packages/core/css/components/canvas-controls.css`
---
# Message composer
Composes text and optional attachments with submission shortcuts and retained drafts on failure.
Category: patterns
Name: `message-composer`
Also known as: MessageComposer, Chat input, Comment composer
Page: https://vlak.dev/components/message-composer/
## When to use
- Chat, comments, or a support reply.
- Async submission that must preserve a draft when it fails.
- Application-owned response generation with a Stop response action.
## When not to
- An arbitrary multi-field form or uploading files without a message.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { MessageComposer } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add message-composer
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/message-composer.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { MessageComposer } from "@noorddev/vlak-react";
sendMessage(text, files)} generating={generating} onStop={stopResponse} allowAttachments accept="image/*,.pdf" />
```
## Props
### MessageComposer
A message draft with attachments, IME-safe shortcuts, and retained text after send failures.
Extends `Omit, "defaultValue" | "onSubmit">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLTextAreaElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | | |
| `defaultValue` | `string` | `""` | |
| `onValueChange` | `(text: string) => void` | | |
| `onSend` (required) | `(message: ComposedMessage) => void \| Promise` | | |
| `label` | `string` | `"Message"` | |
| `placeholder` | `string` | `"Write a message…"` | |
| `disabled` | `boolean` | `false` | |
| `allowAttachments` | `boolean` | `false` | |
| `accept` | `string` | | |
| `maxLength` | `number` | | |
| `sendOnEnter` | `boolean` | `false` | Enter submits, Shift+Enter inserts a line. Otherwise use Cmd/Ctrl+Enter. |
| `generating` | `boolean` | `false` | Application-owned response generation, separate from submission pending state. |
| `onStop` | `() => void` | | Requests that the application stop generation; does not itself cancel a network request. |
## Keyboard
| Keys | Does |
| --- | --- |
| Cmd+Enter, Ctrl+Enter | Submits the draft when no send or response generation is in progress. |
| Enter, Shift+Enter | With sendOnEnter enabled, Enter submits and Shift+Enter inserts a line; IME composition never submits. |
| Tab, Enter, Space | Operates attachment, send, and stop actions. |
## Accessibility
- The textarea has a visible label and shortcut description.
- Sending prevents duplicate submission; results are announced.
- Only a successful send clears the draft and attachments; failures retain both.
- generating replaces Send with Stop response but keeps the next draft editable. onStop requests application cancellation; it does not cancel network activity itself.
## Classes
`rs-message-composer`, `rs-message-composer-actions`, `rs-message-composer-action`, `rs-message-composer-files`, `rs-message-composer-file`, `rs-message-composer-hint`, `rs-message-composer-input`
## Dependencies
Registry dependencies: [textarea](textarea.md), [button](button.md), [icons](icons.md).
React: `packages/react/src/components/message-composer.tsx`
CSS: `packages/core/css/components/message-composer.css`
---
# File browser
Explores a supplied file hierarchy through folders, breadcrumbs, search, and list or grid views.
Category: patterns
Name: `file-browser`
Also known as: FileBrowser, File explorer, Asset browser
Page: https://vlak.dev/components/file-browser/
## When to use
- Browsing a supplied file tree and choosing a file.
- Folder-local search with consistent selection in list and grid views.
## When not to
- Direct filesystem access or cloud storage sync; the application supplies data and actions.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { FileBrowser } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add file-browser
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/file-browser.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { FileBrowser } from "@noorddev/vlak-react";
```
## Props
### FileBrowser
A controlled file collection with folder tree, breadcrumbs, search, and list or grid views.
Extends `Omit, "defaultValue" | "onSelect">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `entries` (required) | `BrowserEntry[]` | | |
| `label` | `string` | `"Files"` | |
| `rootLabel` | `string` | `"Files"` | Visible root-folder name, separate from the accessible browser label. |
| `value` | `string` | | |
| `defaultValue` | `string` | | |
| `onValueChange` | `(id: string) => void` | | |
| `folder` | `string \| null` | | |
| `defaultFolder` | `string \| null` | `null` | |
| `onFolderChange` | `(id: string \| null) => void` | | |
| `onOpen` | `(entry: BrowserEntry) => void` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Arrow keys, Home, End, type-ahead | Navigates the folder tree using its roving focus behavior. |
| Tab, Enter, Space | Uses breadcrumbs, selects files, switches view, and activates Open selected. |
## Accessibility
- Folder tree, breadcrumbs, search, and file collection each have names.
- label names the region and its landmarks; rootLabel supplies the visible root folder name.
- Selected files use aria-pressed and a full surface change.
- Files can be opened by an explicit keyboard-operable action as well as double click.
## Classes
`rs-file-browser`, `rs-file-browser-toolbar`, `rs-file-browser-breadcrumbs`, `rs-file-browser-path`, `rs-file-browser-crumb-item`, `rs-file-browser-crumb`, `rs-file-browser-crumb-current`, `rs-file-browser-action`, `rs-file-browser-body`, `rs-file-browser-tree`, `rs-file-browser-content`, `rs-file-browser-list`, `rs-file-browser-grid`, `rs-file-browser-name`, `rs-file-browser-meta`, `rs-file-browser-empty`, `rs-file-browser-view-active`, `rs-file-browser-item`, `rs-file-browser-tile`, `rs-file-browser-selected`
## Dependencies
Registry dependencies: [icons](icons.md), [input](input.md), [tree-view](tree-view.md).
React: `packages/react/src/components/file-browser.tsx`
CSS: `packages/core/css/components/file-browser.css`
---
# Kanban board
Moves and reorders cards across named columns with drag and keyboard alternatives.
Category: patterns
Name: `kanban-board`
Also known as: KanbanBoard, Task board, Workflow board
Page: https://vlak.dev/components/kanban-board/
## When to use
- Finite work items moving through named states.
- Column changes and ordering that should remain keyboard accessible.
## When not to
- A large virtualised issue tracker or automatic workflow rules.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { KanbanBoard } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add kanban-board
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/kanban-board.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
In progress
Review the proof
```
## Example
```tsx
import { KanbanBoard } from "@noorddev/vlak-react";
```
## Props
### KanbanBoard
Movable cards with drag, keyboard reordering, and named destination selectors.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `columns` (required) | `readonly KanbanColumn[]` | | |
| `value` | `KanbanCard[]` | | |
| `defaultValue` | `KanbanCard[]` | `[]` | |
| `onValueChange` | `(cards: KanbanCard[]) => void` | | |
| `label` | `string` | `"Board"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Alt+Arrow up, Alt+Arrow down | Reorders the focused card handle within its column. |
| Tab, Enter, Space | Operates move up and down buttons and each card's native destination selector. |
## Accessibility
- Every column is a named section; card counts are visible.
- A native destination selector is the keyboard alternative to dragging across columns.
- Moves are announced and disabled cards remain immovable.
## Classes
`rs-kanban-board`, `rs-kanban-columns`, `rs-kanban-column`, `rs-kanban-heading`, `rs-kanban-list`, `rs-kanban-card`, `rs-kanban-card-header`, `rs-kanban-title`, `rs-kanban-detail`, `rs-kanban-controls`, `rs-kanban-destination`, `rs-kanban-reorder`, `rs-kanban-action`, `rs-kanban-status`, `rs-kanban-help`
## Dependencies
Registry dependencies: [native-select](native-select.md), [button](button.md), [icons](icons.md).
React: `packages/react/src/components/kanban-board.tsx`
CSS: `packages/core/css/components/kanban-board.css`
---
# Scheduler
Plans events in agenda, week, or month views with date navigation and accessible rescheduling.
Category: patterns
Name: `scheduler`
Also known as: Scheduler, Event calendar, Agenda
Page: https://vlak.dev/components/scheduler/
## When to use
- An event collection in agenda, week, or month views, using a named timeZone or the browser zone.
- Selecting a new event time or rescheduling while preserving duration.
## When not to
- Recurrence expansion or conflict enforcement; prepare those in the application.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Scheduler } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add scheduler
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/scheduler.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Monday, 7 September
Review09:00–09:30
```
## Example
```tsx
import { Scheduler } from "@noorddev/vlak-react";
```
## Props
### Scheduler
Agenda, week, and month planning in an explicit or browser-local zone. Mutations are callbacks.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `events` (required) | `readonly SchedulerEvent[]` | | |
| `value` | `Date` | | |
| `defaultValue` | `Date` | | |
| `onValueChange` | `(day: Date) => void` | | |
| `view` | `SchedulerView` | | |
| `defaultView` | `SchedulerView` | `"week"` | |
| `onViewChange` | `(view: SchedulerView) => void` | | |
| `onEventSelect` | `(event: SchedulerEvent) => void` | | |
| `onSlotSelect` | `(start: Date) => void` | | |
| `onEventMove` | `(event: SchedulerEvent, next: { start: Date; end: Date; }) => void` | | |
| `weekStart` | `0 \| 1` | `1` | |
| `locale` | `string` | `"en"` | |
| `timeZone` | `string` | | IANA zone, for example Europe/Amsterdam. Defaults to the browser zone. |
| `label` | `string` | `"Schedule"` | |
| `disabled` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Operates date navigation, event buttons, scheduling actions, and view selection. |
| Escape | Closes the rescheduling dialog and returns focus to the triggering action. |
## Accessibility
- Month view is a native table with weekday headers.
- Week columns and navigation are named; native date and time inputs retain platform behavior.
- Rescheduling uses a named native dialog and announces the new time.
- Event Date values and callbacks are instants; date and time inputs use the displayed zone. Invalid intervals and nonexistent daylight-saving times are rejected. Repeated times choose the earlier occurrence.
- Server rendering uses a stable loading shell until hydration so browser time zones and the current date cannot cause a hydration mismatch.
## Classes
`rs-scheduler`, `rs-scheduler-toolbar`, `rs-scheduler-action`, `rs-scheduler-title`, `rs-scheduler-scroll`, `rs-scheduler-week`, `rs-scheduler-date`, `rs-scheduler-month`, `rs-scheduler-weekday`, `rs-scheduler-list`, `rs-scheduler-event`, `rs-scheduler-event-button`, `rs-scheduler-time`, `rs-scheduler-empty`, `rs-scheduler-form`, `rs-scheduler-day`, `rs-scheduler-selected`, `rs-scheduler-cell`, `rs-scheduler-outside`
## Dependencies
Registry dependencies: [button](button.md), [icons](icons.md), [input](input.md), [native-select](native-select.md), [dialog](dialog.md).
React: `packages/react/src/components/scheduler.tsx`
CSS: `packages/core/css/components/scheduler.css`
---
# Health metric
A supplied health reading, unit, time and source with explicit pending, unavailable and stale states.
Category: health
Name: `health-metric`
Also known as: Vital sign, Vital metric, Health reading, Patient observation, Biometric card, Wellness metric
Page: https://vlak.dev/components/health-metric/
## When to use
- Patient summaries and wellness dashboards with a known source for each reading.
- Pass status from the application's data policy; the component does not infer freshness.
- Pass timeLabel with the relevant timezone when a human-readable time is needed.
## When not to
- Deriving a diagnosis, clinical flag or urgency from the number.
- Using zero as a placeholder for missing data; omit value instead.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { HealthMetric } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add health-metric
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/health-metric.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Resting heart rate
64bpm
Last recorded, stale
Wrist sensor
```
## Example
```tsx
import { HealthMetric } from "@noorddev/vlak-react";
```
## Props
### HealthMetric
A sourced reading with explicit data availability, without clinical interpretation.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `string \| number \| null` | | A supplied reading. Zero is a reading; empty strings and non-finite numbers are missing. |
| `unit` | `string` | | |
| `status` | `HealthMetricStatus` | `"available"` | Supplied by the application. Freshness is never inferred from the timestamp. |
| `statusLabel` | `ReactNode` | | |
| `dateTime` | `string` | | |
| `timeLabel` | `string` | | Human-readable time, including the relevant timezone. Falls back to dateTime. |
| `source` | `ReactNode` | | |
| `description` | `ReactNode` | | |
## Accessibility
- Visible labels, units, status, source and time accompany the reading.
- Zero is preserved; empty strings and non-finite values become unavailable. Pending and unavailable states suppress any supplied reading.
- Stale values remain visible with a textual stale label. No clinical status is calculated.
- A native time element preserves the supplied machine-readable timestamp. Native attributes and the div ref pass through.
- The component adds no live region or tab stop. The application can announce updates in context.
## Classes
`rs-health-metric`, `rs-health-metric-label`, `rs-health-metric-reading`, `rs-health-metric-value`, `rs-health-metric-unit`, `rs-health-metric-status`, `rs-health-metric-meta`, `rs-health-metric-description`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/health-metric.tsx`
CSS: `packages/core/css/components/health-metric.css`
---
# Reference range
Positions a supplied numeric reading against caller-supplied reference bounds, with a complete text equivalent.
Category: health
Name: `reference-range`
Also known as: Reference interval, Lab range, Result range, Observation range, Biomarker interval
Page: https://vlak.dev/components/reference-range/
## When to use
- Display numeric bounds supplied by the responsible laboratory or data source.
- Pass valueLabel to format the reading and rangeLabel to identify the source of the interval.
- One-sided intervals are textual; a marker requires two finite, ordered bounds.
## When not to
- Hard-coding a universal normal interval across patients, methods or units.
- Using the marker to indicate a diagnosis, treatment decision or calculated clinical status.
- Comparing a value and bounds expressed in different units.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ReferenceRange } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add reference-range
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/reference-range.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Reported measurement24 units
Supplied reference interval20–30 units
```
## Example
```tsx
import { ReferenceRange } from "@noorddev/vlak-react";
```
## Props
### ReferenceRange
A supplied numeric reference interval. Position describes arithmetic, never clinical status.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `value` | `number \| null` | | |
| `minimum` | `number \| null` | | Caller-supplied lower bound. Omit for an upper bound only. |
| `maximum` | `number \| null` | | Caller-supplied upper bound. Omit for a lower bound only. |
| `unit` | `string` | | |
| `valueLabel` | `string` | | Display formatting for the supplied numeric value. |
| `rangeLabel` | `string` | `"Reference interval"` | Optional contextual label, such as the laboratory's reference interval. |
## Accessibility
- The reading, unit and reference interval are visible as text; decorative geometry is aria-hidden.
- The reference band spans 20% to 80% of the track from the reading direction's start. Outlying markers clamp to the track and have a textual above or below description.
- Missing, non-finite, equal and reversed bounds never produce an invalid marker position. Missing results are named explicitly.
- A one-sided interval is rendered as at least or up to without inventing a second bound.
- The marker remains visible in forced colors. There is no animation, interactive control or clinical classification.
## Classes
`rs-reference-range`, `rs-reference-range-head`, `rs-reference-range-label`, `rs-reference-range-value`, `rs-reference-range-track`, `rs-reference-range-interval`, `rs-reference-range-marker`, `rs-reference-range-bounds`, `rs-reference-range-bound-value`, `rs-reference-range-description`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/reference-range.tsx`
CSS: `packages/core/css/components/reference-range.css`
---
# Lab results
A named collection of supplied laboratory results with units, reference intervals, report times and amendment notes.
Category: health
Name: `lab-results`
Also known as: Laboratory report, Lab panel, Test results, Patient results, Pathology results, Diagnostic report
Page: https://vlak.dev/components/lab-results/
## When to use
- Review numeric and qualitative results from an existing report.
- Supply report states and flags from the source; the component never derives them from a reading.
- Attach note to explain an amendment or unavailable result; provide stable result ids.
## When not to
- Calculating diagnoses, critical-result alerts or treatment recommendations.
- Implying that final means clinically normal or that an amended value is the original report.
- Using the synthetic example values as clinical reference intervals.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { LabResults } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add lab-results
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/lab-results.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Reported measurement
Amended
Result24 units
Replaces the earlier report
Additional analysis
Pending
```
## Example
```tsx
import { LabResults } from "@noorddev/vlak-react";
```
## Props
### LabResults
Supplied laboratory results with explicit report states and optional reference intervals.
Extends `Omit, "results">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLUListElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | Accessible collection name. |
| `results` (required) | `readonly LabResult[]` | | |
| `emptyLabel` | `string` | `"No results available"` | |
## Accessibility
- The root is a native list named by label, with one item per result and a forwarded list ref.
- Final, pending, unavailable and amended states are explicit text; caller-supplied flags supplement the report state.
- Pending and unavailable results hide any supplied value. Zero and qualitative result strings remain valid readings.
- Numeric reference intervals reuse ReferenceRange, including its visible text equivalent and invalid-bound handling.
- An amended report without a reading explicitly says result unavailable. No live announcements are added automatically.
## Classes
`rs-lab-results`, `rs-lab-results-item`, `rs-lab-results-head`, `rs-lab-results-name`, `rs-lab-results-status`, `rs-lab-results-reading`, `rs-lab-results-reading-label`, `rs-lab-results-reading-value`, `rs-lab-results-unit`, `rs-lab-results-note`, `rs-lab-results-time`
## Dependencies
Registry dependencies: [reference-range](reference-range.md).
React: `packages/react/src/components/lab-results.tsx`
CSS: `packages/core/css/components/lab-results.css`
---
# Symptom diary
A chronological record of supplied symptoms and intensity descriptions, with notes and 44px native detail disclosures.
Category: health
Name: `symptom-diary`
Also known as: Symptom journal, Patient diary, Symptom history, Pain diary, Health journal, Patient-reported outcomes
Page: https://vlak.dev/components/symptom-diary/
## When to use
- Read patient-entered symptom history without converting their descriptions into a diagnosis.
- Supply intensity in words or with a named scale; the component does not create severity categories.
- Use actions for application-owned edit or review controls with accessible names and 44px targets.
## When not to
- Triage, diagnosis or urgency inferred from diary text.
- Assuming a missing diary entry means that no symptom occurred.
- Passing ambiguous timestamps; use ISO timestamps with an explicit offset and timeLabel for display.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { SymptomDiary } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add symptom-diary
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/symptom-diary.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Headache
Mild, self-reported
Recorded after breakfast
Details
No additional context recorded
```
## Example
```tsx
import { SymptomDiary } from "@noorddev/vlak-react";
```
## Props
### SymptomDiary
A time-ordered record of supplied symptoms, descriptions and native detail disclosures.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLOListElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `entries` (required) | `readonly SymptomEntry[]` | | |
| `emptyLabel` | `string` | `"No symptoms recorded"` | |
| `order` | `"newest" \| "oldest"` | `"newest"` | Sorts a copy of entries. Equal timestamps retain their supplied order. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses each detail summary and any supplied actions |
| Enter, Space | Opens or closes a focused native detail disclosure |
## Accessibility
- A native ordered list preserves chronological structure. Order defaults to newest first and never mutates the supplied entries.
- Equal timestamps retain input order; invalid timestamps sort last and have no invalid datetime attribute.
- Each disclosure has a unique default name combining symptom and display time; detailsLabel can supply a more precise name.
- Native details and summary provide keyboard toggling. Summaries have 44px targets and a 2px focus ring.
- Intensity and context remain readable text. There are no inferred clinical flags or automatic announcements.
## Classes
`rs-symptom-diary`, `rs-symptom-diary-item`, `rs-symptom-diary-time`, `rs-symptom-diary-content`, `rs-symptom-diary-head`, `rs-symptom-diary-symptom`, `rs-symptom-diary-intensity`, `rs-symptom-diary-body`, `rs-symptom-diary-summary`, `rs-symptom-diary-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/symptom-diary.tsx`
CSS: `packages/core/css/components/symptom-diary.css`
---
# Check-in
Collects one supplied text answer with native radio controls, 44px targets, and an explicit unanswered state.
Category: health
Name: `check-in`
Also known as: CheckIn, Mood check-in, Energy check-in, Wellness check-in, Text rating, Self report
Page: https://vlak.dev/components/check-in/
## When to use
- A daily mood, comfort, or energy check-in with application-owned wording.
- Unique option values and explicit labels for every answer.
- value, defaultValue, and onValueChange with null for an unanswered check-in; name and form submit the selected string.
## When not to
- Inventing a clinical questionnaire, diagnostic interpretation, or score from the selected position.
- Treating an unanswered check-in as a negative answer.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CheckIn } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add check-in
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/check-in.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Choose the answer that fits right now.
```
## Example
```tsx
import { CheckIn } from "@noorddev/vlak-react";
```
## Props
### CheckIn
A named text choice without an inferred clinical score.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `options` (required) | `CheckInOption[]` | | Text answers supplied by the application. Values must be unique. |
| `value` | `string \| null` | | null is an unanswered check-in. |
| `defaultValue` | `string \| null` | `null` | |
| `onValueChange` | `(value: string \| null) => void` | | |
| `required` | `boolean` | | |
| `readOnly` | `boolean` | `false` | |
| `clearable` | `boolean` | `true` | |
| `clearLabel` | `string` | `"Clear answer"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves into the native radio group and then to the available clear action. |
| Arrow keys, Space | Uses native radio selection; read-only answers prevent changes. |
| Enter, Space | Activates the focused clear action. |
## Accessibility
- A fieldset and legend name the answer group; native radios use visible text labels and share a name.
- Every answer covers at least 44px in each dimension, with a focus ring and full-fill selection. Vlak Button supplies the optional clear action.
- Descriptions reach the group and each answer. Read-only controls retain the submitted value and announce their unavailable state.
- Disabled controls do not submit; required uses native radio validation. Form reset restores uncontrolled defaults and preserves controlled values.
- The forwarded ref reaches the fieldset; native fieldset attributes, className, and style pass through.
## Classes
`rs-check-in`, `rs-check-in-legend`, `rs-check-in-description`, `rs-check-in-choices`, `rs-check-in-choice`, `rs-check-in-selected`, `rs-check-in-unavailable`, `rs-check-in-input`, `rs-check-in-clear`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/check-in.tsx`
CSS: `packages/core/css/components/check-in.css`
---
# Habit tracker
Shows dated complete, missed, skipped, and unrecorded states, with controlled completion actions and a responsive week view.
Category: health
Name: `habit-tracker`
Also known as: HabitTracker, Habit calendar, Wellness log, Daily completion, Habit grid
Page: https://vlak.dev/components/habit-tracker/
## When to use
- A week of application-owned habit records, supplied in the intended order.
- Explicit date labels and stable date keys, with no inferred current day or timezone.
- onDayChange to request complete or clear completion to unrecorded; the application updates days and owns persistence.
## When not to
- Inferring missed days from absent records or calculating a punitive streak.
- Assuming a click has been saved without updating and persisting the supplied data.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { HabitTracker } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add habit-tracker
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/habit-tracker.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Evening walk
Mon 7 Sep
✓Complete
Tue 8 Sep
·Unrecorded
```
## Example
```tsx
import { useState } from "react";
import { HabitTracker } from "@noorddev/vlak-react";
import type { HabitDay } from "@noorddev/vlak-react";
function WalkingRecord() {
const [days, setDays] = useState([
{ date: "2026-09-07", label: "Mon 7 Sep", status: "complete" },
{ date: "2026-09-08", label: "Tue 8 Sep", status: "unrecorded" },
]);
return setDays((records) => records.map((day) => day.date === date ? { ...day, status } : day))} />;
}
```
## Props
### HabitTracker
Dated completion records with caller-owned state and no inferred streak.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `days` (required) | `HabitDay[]` | | A supplied week or another dated range, rendered in the given order. |
| `onDayChange` | `(date: string, status: HabitStatus) => void` | | A completion action requests complete, or unrecorded when clearing completion. |
| `disabled` | `boolean` | `false` | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through enabled completion controls when onDayChange is supplied. |
| Enter, Space | Requests completion, or clears an existing completion to unrecorded. |
## Accessibility
- A named group contains an ordered display of supplied day records; every status remains visible as text.
- Completion controls have stable accessible names, aria-pressed, and descriptions that announce complete, missed, skipped, or unrecorded.
- Controls are at least 44px in each dimension; the responsive grid wraps on narrow screens.
- Without onDayChange or with readOnly, records render as static text. Disabled controls do not call onDayChange.
- The forwarded ref and native attributes reach the root div.
## Classes
`rs-habit-tracker`, `rs-habit-tracker-label`, `rs-habit-tracker-description`, `rs-habit-tracker-days`, `rs-habit-tracker-day`, `rs-habit-tracker-date`, `rs-habit-tracker-control`, `rs-habit-tracker-complete`, `rs-habit-tracker-unavailable`, `rs-habit-tracker-static`, `rs-habit-tracker-mark`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/habit-tracker.tsx`
CSS: `packages/core/css/components/habit-tracker.css`
---
# Sleep timeline
Displays supplied sleep, wake, and unknown intervals with explicit time labels, monochrome segments, and a complete text record.
Category: health
Name: `sleep-timeline`
Also known as: SleepTimeline, Sleep log, Sleep chart, Sleep interval, Sleep record, Wellness timeline
Page: https://vlak.dev/components/sleep-timeline/
## When to use
- Display-only sleep records from a caller-owned source, using minute offsets on a single timeline.
- Explicit boundary labels that include the date and timezone when needed.
- Gaps remain unrecorded; supplied unknown intervals retain their unknown state.
## When not to
- Inferring sleep stages, diagnosis, or sleep quality from the supplied intervals.
- Silently clipping out-of-window records, merging overlaps, or filling missing time with sleep.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { SleepTimeline } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add sleep-timeline
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/sleep-timeline.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Last night
22:3006:30
Asleep22:30 to 04:30
Awake04:30 to 06:30
```
## Example
```tsx
import { SleepTimeline } from "@noorddev/vlak-react";
```
## Props
### SleepTimeline
Supplied sleep and wake intervals, with gaps exposed as unrecorded time.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `intervals` (required) | `SleepInterval[]` | | |
| `start` (required) | `number` | | Visible window in minutes. All intervals must fit within it. |
| `end` (required) | `number` | | |
| `startLabel` (required) | `string` | | |
| `endLabel` (required) | `string` | | |
## Accessibility
- A native figure and caption introduce the record. The decorative chart is hidden from assistive technology.
- Every supplied interval and unrecorded gap has a visible text equivalent with start and end labels.
- Overlapping, invalid, or out-of-window intervals produce a visible explanation and suppress the chart while preserving supplied text.
- Sleep, wake, and unknown segments use distinct monochrome fills and boundaries; forced-colors retains a dotted unknown marker.
- The forwarded ref and native attributes reach the figure.
## Classes
`rs-sleep-timeline`, `rs-sleep-timeline-caption`, `rs-sleep-timeline-label`, `rs-sleep-timeline-description`, `rs-sleep-timeline-chart`, `rs-sleep-timeline-segment`, `rs-sleep-timeline-asleep`, `rs-sleep-timeline-awake`, `rs-sleep-timeline-unknown`, `rs-sleep-timeline-axis`, `rs-sleep-timeline-list`, `rs-sleep-timeline-interval`, `rs-sleep-timeline-period`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/sleep-timeline.tsx`
CSS: `packages/core/css/components/sleep-timeline.css`
---
# Activity goal
Shows a supplied activity amount and target with native progress, visible units, and distinct missing-data states.
Category: health
Name: `activity-goal`
Also known as: ActivityGoal, Activity progress, Movement goal, Hydration goal, Step goal, Wellness goal
Page: https://vlak.dev/components/activity-goal/
## When to use
- Movement, hydration, or another activity with a caller-supplied amount, unit, and positive target.
- null for missing current data or an unset target; zero remains a valid recorded amount.
- Actual values above the target remain visible while the native bar stops at its maximum.
## When not to
- Adding default health recommendations or interpreting goal completion as a clinical outcome.
- An indeterminate loading state; missing data is explicitly labelled and has no progress bar.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ActivityGoal } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add activity-goal
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/activity-goal.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Walking
Your personal goal for today
24 of 30 min
```
## Example
```tsx
import { ActivityGoal } from "@noorddev/vlak-react";
```
## Props
### ActivityGoal
Progress toward a supplied activity goal, without recommended targets or scores.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `current` (required) | `number \| null` | | A supplied amount. null means no recorded amount; zero is a valid record. |
| `target` (required) | `number \| null` | | A positive caller-owned goal. null means no goal has been set. |
| `unit` (required) | `string` | | |
## Accessibility
- The native progress element is named by the visible label, aria-label, or aria-labelledby; aria-valuetext includes the actual amount, target, and unit.
- Missing, non-finite, negative amounts and non-positive targets have explicit text states and never produce a misleading bar or NaN attributes.
- Goal reached and goal exceeded remain text, with no color-only completion signal.
- The forwarded ref and native attributes reach the root div; descriptions are linked to progress.
## Classes
`rs-activity-goal`, `rs-activity-goal-label`, `rs-activity-goal-description`, `rs-activity-goal-value`, `rs-activity-goal-target`, `rs-activity-goal-progress`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/activity-goal.tsx`
CSS: `packages/core/css/components/activity-goal.css`
---
# Activity rings
Shows one to six personal goals as concentric rings with a staggered entrance, gentle rotating encouragement, named progress and explicit missing-data states.
Category: health
Name: `activity-rings`
Also known as: Activity ring, Fitness rings, Goal rings, Move rings, Wellness progress, Concentric progress
Page: https://vlak.dev/components/activity-rings/
## When to use
- One activity ring or a compact set of personal movement, routine, or wellness goals.
- Supply goals in outer-to-inner order, with unique ids, labels, amounts, targets, and units.
- Pair with ActivityGoal for a linear progress view of the same data.
- Rings sweep into their supplied values on first view and ease into later updates. Set animate to false for an instant graphic.
- Encouragement picks a different line every ten seconds while visible. Supply your own encouragement strings, one string for a static line, or false to hide it. The first line stays deterministic during server rendering.
## When not to
- Deriving a readiness score, calorie prescription, or recommended target.
- Treating an unrecorded amount as zero. More than six goals retain their text records without a ring graphic.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ActivityRings } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add activity-rings
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/activity-rings.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Daily activity
01
Walking
18 of 30 minutes
```
## Example
```tsx
import { ActivityRings } from "@noorddev/vlak-react";
```
## Props
### ActivityRings
Concentric personal-goal progress, with a complete named record for each ring.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `goals` (required) | `readonly ActivityRingGoal[]` | | One to six goals are drawn from the outside inward. Every goal retains a text record. |
| `description` | `ReactNode` | | |
| `animate` | `boolean` | `true` | Sweep each ring into its supplied value on first view. Reduced motion stays instant. |
| `encouragement` | `false \| readonly string[]` | `defaultEncouragement` | Gentle lines rotate every ten seconds without immediate repetition. false hides the line. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves to the encouragement pause control when rotation is available. |
| Enter, Space | Pauses or resumes encouraging text rotation. |
## Accessibility
- Every valid goal has a named native progress element and an explicit amount, target, and unit.
- Concentric geometry is decorative. Visible numbering and outer-to-inner order connect the rings with their text records without relying on hue.
- Zero stays empty, amounts above target retain their actual value, and missing or invalid data has no progress arc.
- The figure forwards its native attributes and ref, and rings remain visible in forced colors. Actual readings and native progress values update immediately throughout the decorative entrance.
- Reduced motion makes ring fills instant and keeps encouragement static. Rotation also pauses while the figure is offscreen or the document is hidden.
- A 44px keyboard-accessible control pauses or resumes rotation. Encouragement has no automatic live announcement; text remains available in the reading order.
## Classes
`rs-activity-rings`, `rs-activity-rings-caption`, `rs-activity-rings-body`, `rs-activity-rings-graphic`, `rs-activity-rings-track`, `rs-activity-rings-arc`, `rs-activity-rings-list`, `rs-activity-rings-item`, `rs-activity-rings-index`, `rs-activity-rings-label`, `rs-activity-rings-value`, `rs-activity-rings-target`, `rs-activity-rings-note`, `rs-activity-rings-description`, `rs-activity-rings-progress`, `rs-activity-rings-motion`, `rs-activity-rings-waiting`, `rs-activity-rings-encouragement`, `rs-activity-rings-encouragement-text`, `rs-activity-rings-pause`, `rs-activity-rings-pause-icon`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/activity-rings.tsx`
CSS: `packages/core/css/components/activity-rings.css`
---
# Patient banner
Keeps a supplied patient identity, identifiers, and recorded context together in a responsive band.
Category: health
Name: `patient-banner`
Also known as: PatientBanner, Patient header, Patient summary, Clinical context, EHR header
Page: https://vlak.dev/components/patient-banner/
## When to use
- Patient record headers and care workspaces where identity and recorded context must stay together.
- Supply explicit values such as Unknown, Not reviewed, or None recorded according to the actual source record.
## When not to
- Inferring age from a birth date or treating missing context as no allergies.
- Urgent notifications that need a live announcement; the banner is static context.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { PatientBanner } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add patient-banner
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/patient-banner.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Robin Ellis
Patient ID
Demo 042
Allergies
Not reviewed
```
## Example
```tsx
import { PatientBanner } from "@noorddev/vlak-react";
```
## Props
### PatientBanner
A supplied patient identity and explicitly recorded context, without clinical inference.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `patientName` (required) | `string` | | Caller-supplied identity. No age or other demographic values are inferred. |
| `identifiers` | `readonly PatientBannerIdentifier[]` | `[]` | |
| `contextItems` | `readonly PatientBannerContextItem[]` | `[]` | |
| `identifiersEmptyLabel` | `ReactNode` | `"Identifiers not supplied"` | |
| `contextEmptyLabel` | `ReactNode` | `"Patient context not supplied"` | Missing context never means that no allergies or alerts exist. |
## Keyboard
| Keys | Does |
| --- | --- |
| None | Static identity and description lists add no keyboard stop. Any supplied child controls keep their native behavior. |
## Accessibility
- The patient name labels a group; identifiers and context use dl, dt, and dd in reading order.
- Unknown and none-recorded distinctions are supplied as visible text. Empty defaults describe missing data without making clinical claims.
- The root forwards its div ref, native attributes, className, and style.
## Classes
`rs-patient-banner`, `rs-patient-banner-name`, `rs-patient-banner-identifiers`, `rs-patient-banner-field`, `rs-patient-banner-label`, `rs-patient-banner-value`, `rs-patient-banner-context`, `rs-patient-banner-missing`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/patient-banner.tsx`
CSS: `packages/core/css/components/patient-banner.css`
---
# Medication schedule
Lists supplied medication, dose, time, and recorded status with controlled 44px recording actions.
Category: health
Name: `medication-schedule`
Also known as: MedicationSchedule, Medication list, Medication record, Dose log, Medication administration record
Page: https://vlak.dev/components/medication-schedule/
## When to use
- Displaying an existing medication schedule and requesting explicit record updates.
- Supply timezone, dosing text, instructions, action labels, and recorded statuses from the application.
## When not to
- Calculating doses, suggesting medication, guessing overdue entries, or declaring a record saved from a click alone.
- Treating an empty list as evidence that a patient takes no medication.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { MedicationSchedule } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add medication-schedule
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/medication-schedule.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
14 SeptemberEurope/Amsterdam, UTC+02:00
08:00
Example medication
Dose supplied by the care team
Not recorded
```
## Example
```tsx
import { MedicationSchedule } from "@noorddev/vlak-react";
// For editing, pass explicit item.actions and onAction(itemId, actionId).
// The caller persists the choice, sets item.pending, and supplies the new status.
```
## Props
### MedicationSchedule
A controlled record of supplied medication rows, not a dosing or reminder engine.
Extends `Omit, "onAction">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` (required) | `readonly MedicationScheduleItem[]` | | |
| `timeZone` (required) | `ReactNode` | | Display label supplied by the application, including any relevant UTC offset. |
| `dateLabel` | `ReactNode` | | |
| `emptyLabel` | `ReactNode` | `"No medication entries supplied"` | |
| `onAction` | `(itemId: string, actionId: string) => void` | | Requests a record change. The caller persists it and supplies updated items. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between enabled recording buttons when onAction and item actions are supplied. |
| Enter, Space | Requests the selected recording action. Pending or disabled rows cannot request changes. |
## Accessibility
- Rows remain in supplied order in an ordered list. Optional dateTime values are passed through unchanged.
- Action names include the visible action label and medication name. Each action is described by its scheduled time, dose, and recorded status to distinguish repeated doses. Buttons have at least 44px targets.
- Pending state remains visible alongside the existing status, uses aria-busy and a polite status region, and disables recording actions.
- No internal persistence or automatic success state. Without onAction the schedule is read-only.
## Classes
`rs-medication-schedule`, `rs-medication-schedule-header`, `rs-medication-schedule-zone`, `rs-medication-schedule-list`, `rs-medication-schedule-row`, `rs-medication-schedule-time`, `rs-medication-schedule-body`, `rs-medication-schedule-name`, `rs-medication-schedule-detail`, `rs-medication-schedule-status`, `rs-medication-schedule-actions`, `rs-medication-schedule-action`, `rs-medication-schedule-empty`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/medication-schedule.tsx`
CSS: `packages/core/css/components/medication-schedule.css`
---
# Appointment card
Groups supplied appointment time, timezone, clinician, location, and status with an optional action slot.
Category: health
Name: `appointment-card`
Also known as: AppointmentCard, Visit card, Booking card, Care appointment, Consultation details
Page: https://vlak.dev/components/appointment-card/
## When to use
- Confirmed, proposed, cancelled, or otherwise explicitly supplied appointments.
- Add real links or buttons as children when navigation or an action is available.
## When not to
- Inferring confirmation, converting timezones, or deriving a relative date from the system clock.
- Rendering placeholder Join, Cancel, or Reschedule buttons without working actions.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { AppointmentCard } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add appointment-card
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/appointment-card.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Care team check-in
Confirmed
18 September 202610:30–11:00 · Europe/Amsterdam, UTC+02:00
Clinician
Alex Morgan
Location
Room 04, demo clinic
```
## Example
```tsx
import { AppointmentCard } from "@noorddev/vlak-react";
// Supply children for real navigation links or application-owned actions.
```
## Props
### AppointmentCard
Appointment details exactly as supplied, with an application-owned action slot.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `appointmentTitle` (required) | `string` | | |
| `dateLabel` (required) | `ReactNode` | | |
| `timeLabel` (required) | `ReactNode` | | |
| `timeZone` (required) | `ReactNode` | | Supplied display timezone; the component performs no date conversion. |
| `dateTime` | `string` | | |
| `clinician` | `ReactNode` | | |
| `location` | `ReactNode` | | |
| `status` (required) | `ReactNode` | | |
| `children` | `ReactNode` | | Actual links or buttons whose actions are owned by the application. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Supplied links and buttons retain their native keyboard interactions. The card adds no tab stop. |
## Accessibility
- Appointment title names a group. Date, time, timezone, and status are text; clinician and location use a description list.
- Missing clinician and location are explicitly labelled as not supplied.
- Use native action controls with accessible names and at least 44px targets in the children slot.
- Native root attributes and the div ref pass through. The caller owns status updates and announcements.
## Classes
`rs-appointment-card`, `rs-appointment-card-header`, `rs-appointment-card-title`, `rs-appointment-card-status`, `rs-appointment-card-when`, `rs-appointment-card-date`, `rs-appointment-card-time`, `rs-appointment-card-details`, `rs-appointment-card-field`, `rs-appointment-card-label`, `rs-appointment-card-value`, `rs-appointment-card-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/appointment-card.tsx`
CSS: `packages/core/css/components/appointment-card.css`
---
# Care plan
Lists supplied care tasks, owners, due labels, and statuses with controlled completion requests.
Category: health
Name: `care-plan`
Also known as: CarePlan, Care tasks, Patient checklist, Care coordination, Treatment task list
Page: https://vlak.dev/components/care-plan/
## When to use
- Existing care plans with named owners and application-supplied deadlines and task status.
- Supply an explicit completed boolean and onCompletedChange to enable a completion control.
## When not to
- Generating treatment plans or deriving task urgency from dates.
- Treating an unknown completion state as unchecked or showing success before the caller updates the record.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CarePlan } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add care-plan
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/care-plan.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Confirm the next visit
Owner
Robin Ellis
Due
17 September
Status
Open
```
## Example
```tsx
import { CarePlan } from "@noorddev/vlak-react";
// Pass onCompletedChange(taskId, completed) to request changes.
// The caller persists completion and supplies updated tasks and pending states.
```
## Props
### CarePlan
A supplied care task list with controlled completion requests and explicit pending states.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `tasks` (required) | `readonly CarePlanTask[]` | | |
| `description` | `ReactNode` | | |
| `emptyLabel` | `ReactNode` | `"No care tasks supplied"` | |
| `onCompletedChange` | `(taskId: string, completed: boolean) => void` | | Requests a change only. Persist it and return updated tasks from the caller. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between enabled completion checkboxes when editing is available. |
| Space | Requests a completion change through onCompletedChange. The checkbox stays at the supplied value until the caller updates it. |
## Accessibility
- Task labels name native checkboxes with at least 44px label targets; the recorded status describes each checkbox.
- Pending or disabled tasks cannot be changed. Pending text is visible in a polite status region with aria-busy on the task.
- Tasks with unknown completion or no change callback render as static text, without an invented checkbox state.
- Owner and due-date omissions are explicitly marked as not supplied. Dates are never parsed or inferred.
## Classes
`rs-care-plan`, `rs-care-plan-description`, `rs-care-plan-list`, `rs-care-plan-row`, `rs-care-plan-title`, `rs-care-plan-check`, `rs-care-plan-detail`, `rs-care-plan-metadata`, `rs-care-plan-field`, `rs-care-plan-label`, `rs-care-plan-value`, `rs-care-plan-pending`, `rs-care-plan-empty`
## Dependencies
Registry dependencies: [checkbox](checkbox.md).
React: `packages/react/src/components/care-plan.tsx`
CSS: `packages/core/css/components/care-plan.css`
---
# Identity document
Displays a supplied credential, masked identifier, issuer, dates, and verification status without exposing a raw identifier.
Category: civic
Name: `identity-document`
Also known as: IdentityDocument, Credential record, Identity card, Residence permit, Identity verification, Document summary
Page: https://vlak.dev/components/identity-document/
## When to use
- Identity documents, professional credentials, and permit records using an already-masked display identifier.
- Supply verification status and date labels from the host; add real links or actions as children.
## When not to
- Passing a full identifier and expecting this component to redact it. It renders maskedIdentifier exactly as supplied.
- Inferring validity from an expiry date, or providing a cosmetic reveal button without an authorized source.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { IdentityDocument } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add identity-document
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/identity-document.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Residence document
Verification pending
Robin Ellis
Document number
•••• 2048
```
## Example
```tsx
import { IdentityDocument } from "@noorddev/vlak-react";
```
## Props
### IdentityDocument
A credential record using only the supplied, display-safe identity information.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `documentTitle` (required) | `string` | | |
| `holderName` (required) | `ReactNode` | | |
| `maskedIdentifier` | `string \| null` | | A display-safe, already-masked identifier. This component does not mask raw data. |
| `identifierLabel` | `string` | `"Document number"` | |
| `issuer` | `ReactNode` | | |
| `issuedLabel` | `ReactNode` | | |
| `expiresLabel` | `ReactNode` | | |
| `status` (required) | `ReactNode` | | Supplied record or verification status. Expiry is never calculated. |
| `statusDetail` | `ReactNode` | | |
| `children` | `ReactNode` | | Working links or application-owned actions. No reveal or copy action is generated. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Supplied native links and buttons keep their keyboard behavior. The document adds no tab stop. |
## Accessibility
- A named group and description list preserve document fields in reading order.
- Missing identifier, issuer, and dates are explicitly labelled as not supplied. Status is visible text.
- Root attributes, className, style, and the div ref pass through. Supply child controls with at least 44px targets.
## Classes
`rs-identity-document`, `rs-identity-document-header`, `rs-identity-document-title`, `rs-identity-document-status`, `rs-identity-document-holder`, `rs-identity-document-fields`, `rs-identity-document-field`, `rs-identity-document-label`, `rs-identity-document-value`, `rs-identity-document-detail`, `rs-identity-document-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/identity-document.tsx`
CSS: `packages/core/css/components/identity-document.css`
---
# Tax summary
Separates supplied assessment line items from authoritative totals in a semantic two-column table.
Category: civic
Name: `tax-summary`
Also known as: TaxSummary, Tax assessment, Assessment statement, Municipal charges, Tax bill, Refund statement
Page: https://vlak.dev/components/tax-summary/
## When to use
- Tax assessments, municipal charges, and other supplied statements with separate line items and totals.
- Pass fully formatted amounts, signs, currencies, period, payment timing, and status from the authoritative source.
## When not to
- Computing taxes, estimating refunds, summing amounts, or assuming a missing total is zero.
- Generating a payment action or deadline without an application-owned destination or supplied terms.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { TaxSummary } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add tax-summary
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/tax-summary.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
ProvisionalExample 204
Annual assessment2025
Item
Amount
Assessed amount
€ 240.00
Amount payable
€ 240.00
```
## Example
```tsx
import { TaxSummary } from "@noorddev/vlak-react";
```
## Props
### TaxSummary
A supplied assessment with distinct line items and authoritative totals.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `periodLabel` (required) | `ReactNode` | | |
| `reference` | `ReactNode` | | |
| `status` (required) | `ReactNode` | | |
| `items` (required) | `readonly TaxSummaryItem[]` | | |
| `totals` (required) | `readonly TaxSummaryTotal[]` | | |
| `dueLabel` | `ReactNode` | | |
| `note` | `ReactNode` | | |
| `itemsEmptyLabel` | `ReactNode` | `"Assessment lines not supplied"` | |
| `totalsEmptyLabel` | `ReactNode` | `"Totals not supplied"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Only supplied child controls enter the tab order and retain native keyboard behavior. |
## Accessibility
- A caption names the table; scope attributes associate row and column headers with amount cells.
- Line items use tbody and supplied totals use tfoot. Amounts remain literal readable text.
- Missing line items, totals, reference, and timing have explicit text. No numeric or financial status is inferred.
- Native div attributes and refs pass through; child action targets should be at least 44px.
## Classes
`rs-tax-summary`, `rs-tax-summary-header`, `rs-tax-summary-status`, `rs-tax-summary-reference`, `rs-tax-summary-table`, `rs-tax-summary-caption`, `rs-tax-summary-period`, `rs-tax-summary-column`, `rs-tax-summary-row-label`, `rs-tax-summary-amount`, `rs-tax-summary-detail`, `rs-tax-summary-total`, `rs-tax-summary-footer`, `rs-tax-summary-note`, `rs-tax-summary-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/tax-summary.tsx`
CSS: `packages/core/css/components/tax-summary.css`
---
# Benefit program
Keeps programme availability, supplied eligibility, award terms, and criterion assessments separate.
Category: civic
Name: `benefit-program`
Also known as: BenefitProgram, Grant programme, Subsidy card, Public benefit, Funding opportunity, Eligibility summary
Page: https://vlak.dev/components/benefit-program/
## When to use
- Public benefits, grants, subsidies, and funding opportunities with source-owned eligibility assessments.
- Display programme availability separately from an applicant’s eligibility and the programme’s award terms.
## When not to
- Deciding eligibility from criteria, personal data, income, or a model-generated recommendation.
- Implying an award is approved because applications are open or some criteria are satisfied.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { BenefitProgram } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add benefit-program
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/benefit-program.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Community project grant
Applications open
Your eligibility
Not assessed
Award
Award amount not supplied
Project locationNot reviewed
```
## Example
```tsx
import { BenefitProgram } from "@noorddev/vlak-react";
```
## Props
### BenefitProgram
Programme availability, supplied eligibility, and award terms kept as distinct facts.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `programName` (required) | `string` | | |
| `provider` | `ReactNode` | | |
| `status` (required) | `ReactNode` | | Supplied programme availability, separate from a person's eligibility. |
| `eligibility` (required) | `ReactNode` | | |
| `awardLabel` | `ReactNode` | | |
| `awardDetails` | `ReactNode` | | |
| `deadlineLabel` | `ReactNode` | | |
| `criteria` (required) | `readonly BenefitProgramCriterion[]` | | |
| `description` | `ReactNode` | | |
| `criteriaEmptyLabel` | `ReactNode` | `"Eligibility criteria not supplied"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Supplied action links and buttons use native keyboard behavior. Criteria are static readable items. |
## Accessibility
- Programme name labels a group; programme facts use a description list and criteria use a named list.
- Eligibility, criterion status, and programme availability are visible text rather than color-only indicators.
- Missing provider, award, deadline, or criteria are explicitly described. Native root attributes and div refs pass through.
- Provide working child controls with at least 44px targets when an application or information action is available.
## Classes
`rs-benefit-program`, `rs-benefit-program-header`, `rs-benefit-program-name`, `rs-benefit-program-status`, `rs-benefit-program-detail`, `rs-benefit-program-facts`, `rs-benefit-program-field`, `rs-benefit-program-label`, `rs-benefit-program-value`, `rs-benefit-program-criteria`, `rs-benefit-program-criterion`, `rs-benefit-program-criterion-head`, `rs-benefit-program-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/benefit-program.tsx`
CSS: `packages/core/css/components/benefit-program.css`
---
# Application status
Shows a supplied case reference, status, update time, milestones, and next step without estimating progress.
Category: civic
Name: `application-status`
Also known as: ApplicationStatus, Case status, Application tracker, Permit status, Claim progress, Case timeline
Page: https://vlak.dev/components/application-status/
## When to use
- Permit, benefits, tax, and grant cases with supplied status and milestones.
- Supply the current milestone explicitly, preserve source milestone order, and use nextStep for the authority’s actual instruction.
## When not to
- Predicting approval, calculating completion percentages, or choosing the current step from dates.
- Presenting estimated service times as confirmed decision dates.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ApplicationStatus } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add application-status
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/application-status.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Community grant application
Example 204
Under review
Updated 14 September, as supplied
Evidence reviewIn progress
Next step
Wait for the review update
```
## Example
```tsx
import { ApplicationStatus } from "@noorddev/vlak-react";
```
## Props
### ApplicationStatus
A case reference, explicit decision status, and supplied milestones with no inferred progress.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `applicationTitle` (required) | `string` | | |
| `reference` | `ReactNode` | | |
| `status` (required) | `ReactNode` | | |
| `statusDetail` | `ReactNode` | | |
| `updatedLabel` | `ReactNode` | | |
| `milestones` (required) | `readonly ApplicationMilestone[]` | | |
| `nextStep` | `ReactNode` | | |
| `milestonesEmptyLabel` | `ReactNode` | `"Application milestones not supplied"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Enter, Space | Any supplied child links or buttons keep their native keyboard behavior. Milestones are not interactive. |
## Accessibility
- An ordered, named list preserves milestone order. Explicit current milestones use aria-current=step and a full-surface fill.
- Status and dates are readable text. Optional machine-readable milestone dates are passed through without conversion.
- Missing reference, update time, milestone dates, milestones, and next step have explicit descriptions.
- The root forwards native div attributes and its ref. Use at least 44px targets for supplied actions.
## Classes
`rs-application-status`, `rs-application-status-header`, `rs-application-status-title`, `rs-application-status-reference`, `rs-application-status-overview`, `rs-application-status-status`, `rs-application-status-detail`, `rs-application-status-milestones`, `rs-application-status-milestone`, `rs-application-status-current`, `rs-application-status-milestone-label`, `rs-application-status-milestone-meta`, `rs-application-status-next`, `rs-application-status-next-label`, `rs-application-status-actions`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/application-status.tsx`
CSS: `packages/core/css/components/application-status.css`
---
# Evidence checklist
Lists evidence requirements, file records, and supplied verification status with controlled 44px action buttons.
Category: civic
Name: `evidence-checklist`
Also known as: EvidenceChecklist, Document checklist, Supporting documents, Evidence requirements, Application documents, Verification checklist
Page: https://vlak.dev/components/evidence-checklist/
## When to use
- Evidence requirements for permits, grants, benefits, and identity checks.
- Provide explicit actions for working uploads, downloads, replacements, or record changes through the host callback.
## When not to
- Marking evidence accepted from a filename or a button click, or inferring requirements from missing values.
- Treating uploads as submitted before the host confirms them, or rendering dead action buttons without a callback.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { EvidenceChecklist } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add evidence-checklist
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/evidence-checklist.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Application evidence
Proof of address
Required by the provider
Example-address.pdf
Awaiting review
```
## Example
```tsx
import { EvidenceChecklist } from "@noorddev/vlak-react";
// To enable actions, supply item.actions and onAction(itemId, actionId).
// The host performs uploads or changes and supplies pending and updated status.
```
## Props
### EvidenceChecklist
Evidence requirements, file records, and verification status with controlled action requests.
Extends `Omit, "onAction">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `items` (required) | `readonly EvidenceChecklistItem[]` | | |
| `summary` | `ReactNode` | | Application-supplied coverage summary; the component does not count approvals. |
| `emptyLabel` | `ReactNode` | `"Evidence requirements not supplied"` | |
| `onAction` | `(itemId: string, actionId: string) => void` | | Requests an action only; uploads, removals, and resulting statuses belong to the caller. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between enabled evidence action buttons when onAction and item actions are supplied. |
| Enter, Space | Requests the focused item action without mutating the displayed record. Pending or disabled actions cannot be activated. |
## Accessibility
- Action names contain the visible label and evidence name; descriptions include requirement, file record, and supplied status.
- Record status uses a polite atomic status region. Pending text remains visible and actionable controls are disabled without hiding the existing status.
- No checkboxes or completion percentage are invented from verification status. Missing requirements or file details are explicitly labelled.
- Buttons have at least 44px targets. Native root attributes, className, style, and div refs pass through.
## Classes
`rs-evidence-checklist`, `rs-evidence-checklist-heading`, `rs-evidence-checklist-summary`, `rs-evidence-checklist-list`, `rs-evidence-checklist-item`, `rs-evidence-checklist-head`, `rs-evidence-checklist-label`, `rs-evidence-checklist-requirement`, `rs-evidence-checklist-detail`, `rs-evidence-checklist-record`, `rs-evidence-checklist-status`, `rs-evidence-checklist-actions`, `rs-evidence-checklist-action`, `rs-evidence-checklist-empty`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/evidence-checklist.tsx`
CSS: `packages/core/css/components/evidence-checklist.css`
---
# Measurement value
A supplied scientific reading with units, symmetric uncertainty, optional scientific notation and explicit availability.
Category: science
Name: `measurement-value`
Also known as: Scientific measurement, Uncertainty display, Measured value, Scientific notation, Metrology reading
Page: https://vlak.dev/components/measurement-value/
## When to use
- Scientific observations with application-supplied uncertainty and units.
- Pass a string to preserve significant figures such as 1.230; scientific notation formats numeric inputs without selecting a precision.
- Use uncertaintyLabel to name the supplied uncertainty convention.
## When not to
- Inferring significant figures, a confidence level, a distribution or unit conversions.
- Treating zero as missing, or using a negative uncertainty to express asymmetric bounds.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { MeasurementValue } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add measurement-value
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/measurement-value.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Sample mass
1.230± 0.005g
Supplied uncertainty
```
## Example
```tsx
import { MeasurementValue } from "@noorddev/vlak-react";
```
## Props
### MeasurementValue
A supplied scientific reading without inferred precision, confidence or unit conversion.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `string \| number \| null` | | Strings preserve supplied significant figures. Non-finite numbers are unavailable. |
| `unit` | `string` | | |
| `uncertainty` | `number \| null` | | A supplied symmetric, non-negative uncertainty in the same unit as value. |
| `uncertaintyLabel` | `ReactNode` | | |
| `notation` | `"plain" \| "scientific"` | `"plain"` | Scientific notation changes numeric formatting only; supplied strings are unchanged. |
| `status` | `"pending" \| "unavailable" \| "recorded"` | `"recorded"` | |
| `source` | `ReactNode` | | |
| `description` | `ReactNode` | | |
## Accessibility
- The reading, plus-minus uncertainty, unit and source remain visible text.
- Pending and unavailable states suppress the numeric reading. Zero is preserved, while empty strings and non-finite values are unavailable.
- Negative or non-finite uncertainty is explicitly unavailable without hiding a valid reading.
- The div ref, native attributes, className and style pass through. No automatic announcements or interactive stops are added.
## Classes
`rs-measurement-value`, `rs-measurement-value-label`, `rs-measurement-value-reading`, `rs-measurement-value-number`, `rs-measurement-value-uncertainty`, `rs-measurement-value-unit`, `rs-measurement-value-context`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/measurement-value.tsx`
CSS: `packages/core/css/components/measurement-value.css`
---
# Quantity field
A 44px Vlak numeric input and styled unit selector with controlled quantity values, form submission and reset support.
Category: science
Name: `quantity-field`
Also known as: Unit input, Scientific input, Dimensioned number, Amount and unit, Measurement input
Page: https://vlak.dev/components/quantity-field/
## When to use
- Dimensioned quantities with explicit unit choices and native numeric constraints.
- name submits the amount and unitName submits the unit, defaulting to name followed by .unit.
- Supply value and onValueChange when the application converts units or persists the result; unit selection alone keeps the supplied amount unchanged.
- null represents a missing amount or unit. Unit option values must be unique and non-empty.
## When not to
- Assuming that choosing a different unit automatically converts the amount.
- Relying on formatting to establish scientific precision or dimensional compatibility.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { QuantityField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add quantity-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/quantity-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Unit
```
## Example
```tsx
import { QuantityField } from "@noorddev/vlak-react";
```
## Props
### QuantityField
A native numeric input and unit selector. Selection never converts the amount.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `units` (required) | `readonly QuantityUnit[]` | | |
| `value` | `QuantityValue` | | |
| `defaultValue` | `QuantityValue` | `{ amount: null, unit: null }` | |
| `onValueChange` | `(value: QuantityValue) => void` | | Requests a quantity change. A unit change preserves the amount; the host owns conversion. |
| `description` | `ReactNode` | | |
| `unitName` | `string` | `name ? \`${name}.unit\` : undefined` | Input names: name submits the amount; unitName defaults to name + '.unit'. |
| `amountLabel` | `string` | `"Amount"` | |
| `unitLabel` | `string` | `"Unit"` | |
| `unitPlaceholder` | `string` | `"Choose unit"` | |
| `min` | `number` | | |
| `max` | `number` | | |
| `step` | `number \| "any"` | `"any"` | |
| `required` | `boolean` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between the amount input and unit selector. |
| Arrow keys | Uses native number stepping or opens and navigates the Vlak unit selector. Enter or Space confirms a unit; Escape closes its menu. |
## Accessibility
- A fieldset and legend name the quantity. Vlak Input and Select have visible labels, descriptions and 44px targets.
- Required, min, max and step use native validation. Invalid supplied numbers and unknown units have explicit text states.
- Native form reset restores uncontrolled defaults and leaves controlled values with the application.
- Read-only quantities preserve the submitted amount and unit while preventing edits. Disabled quantities do not submit.
- The fieldset ref and native attributes pass through; no unit is chosen implicitly.
## Classes
`rs-quantity-field`, `rs-quantity-field-legend`, `rs-quantity-field-row`, `rs-quantity-field-label`, `rs-quantity-field-control`, `rs-quantity-field-description`
## Dependencies
Registry dependencies: [input](input.md), [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/quantity-field.tsx`
CSS: `packages/core/css/components/quantity-field.css`
---
# Well plate
A labelled laboratory plate with supplied well states, 44px selection controls and keyboard navigation across up to 1536 wells.
Category: microbiology
Name: `well-plate`
Also known as: Microplate, Plate map, Microtiter plate, Sample plate, Assay plate, Well grid
Page: https://vlak.dev/components/well-plate/
## When to use
- Sample placement and plate inspection with application-supplied rows, columns and well states.
- Unique row and column labels and at most one record per coordinate. Missing records are labelled Unrecorded.
- Use value and onValueChange for application-owned selection; readOnly provides a static plate.
## When not to
- Inferring empty wells, assay outcomes or sample identities from missing records.
- Layouts larger than 1536 wells; the component reports the limit instead of silently truncating a plate.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { WellPlate } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add well-plate
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/well-plate.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Plate 042
Supplied well records
Well
1
A
A1Loaded
```
## Example
```tsx
import { WellPlate } from "@noorddev/vlak-react";
```
## Props
### WellPlate
A plate of up to 1536 wells, with roving keyboard focus and explicit unrecorded cells.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `rows` (required) | `readonly string[]` | | |
| `columns` (required) | `readonly string[]` | | |
| `wells` (required) | `readonly WellRecord[]` | | |
| `value` | `WellPosition \| null` | | |
| `defaultValue` | `WellPosition \| null` | `null` | |
| `onValueChange` | `(value: WellPosition) => void` | | |
| `description` | `ReactNode` | | |
| `disabled` | `boolean` | `false` | |
| `readOnly` | `boolean` | `false` | Static well cells add no tab stops; their scroll container remains focusable. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Enters the plate at one enabled well and then leaves the grid. |
| Arrow keys | Moves focus along a row or column, skipping disabled wells without changing selection. |
| Home, End | Moves to the first or last enabled well in the current row. |
| Ctrl+Home, Ctrl+End | Moves to the first or last enabled well in the plate. |
| Enter, Space | Selects the focused well. Controlled selection waits for the caller's updated value. |
## Accessibility
- A named grid uses row and column headers, roving button focus and aria-selected cells. Every well name includes its coordinates and supplied state.
- Selected wells use a full fill and controls retain 44px targets. Large plates scroll inside their own container.
- Arrow navigation respects the document reading direction. Disabled wells are skipped; static and fully disabled plates provide one focusable scroll region.
- Duplicate or unknown coordinates and invalid layouts produce a visible explanation instead of an ambiguous plate.
- The root div forwards its ref and native attributes. Selection does not submit a form.
## Classes
`rs-well-plate`, `rs-well-plate-label`, `rs-well-plate-description`, `rs-well-plate-scroll`, `rs-well-plate-table`, `rs-well-plate-heading`, `rs-well-plate-cell`, `rs-well-plate-well`, `rs-well-plate-selected`, `rs-well-plate-unavailable`, `rs-well-plate-static`, `rs-well-plate-coordinate`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/well-plate.tsx`
CSS: `packages/core/css/components/well-plate.css`
---
# Experiment run
Supplied experiment metadata, conditions and ordered protocol steps with explicit statuses and controlled recording actions.
Category: science
Name: `experiment-run`
Also known as: Protocol run, Lab notebook run, Experiment record, Acquisition workflow, Scientific workflow
Page: https://vlak.dev/components/experiment-run/
## When to use
- Lab notebooks, acquisition workspaces and protocol review with supplied run state.
- Pass explicit step actions and onAction to request changes; update supplied statuses after persistence.
- Keep protocol links, conditions and step details with the run they describe.
## When not to
- Inferring completion, experimental validity or the next scientific procedure.
- Treating an action request as proof that an instrument ran or that data was saved.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ExperimentRun } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add experiment-run
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/experiment-run.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Optical measurement
Awaiting review
Run 042
Review acquisitionNot reviewed
```
## Example
```tsx
import { ExperimentRun } from "@noorddev/vlak-react";
```
## Props
### ExperimentRun
Supplied run metadata and protocol steps, with application-owned transitions.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `runId` | `string` | | |
| `protocol` | `ReactNode` | | |
| `status` (required) | `string` | | |
| `conditions` | `readonly ExperimentCondition[]` | `[]` | |
| `steps` (required) | `readonly ExperimentStep[]` | | |
| `onAction` | `(stepId: string, actionId: string) => void` | | Requests an explicit action. State remains supplied by the application. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between supplied links and enabled step actions. |
| Enter, Space | Requests the focused step action through onAction. |
## Accessibility
- A named group contains conditions as a description list and steps as an ordered list.
- Action names include their step number and label; the current step status is their accessible description.
- Pending steps keep their recorded state, show pending text and disable actions. No internal success state is invented.
- Zero-valued conditions remain visible and missing conditions are explicitly labelled. Buttons are at least 44px with visible focus rings.
- The root div forwards native attributes and its ref.
## Classes
`rs-experiment-run`, `rs-experiment-run-head`, `rs-experiment-run-title`, `rs-experiment-run-context`, `rs-experiment-run-conditions`, `rs-experiment-run-value`, `rs-experiment-run-list`, `rs-experiment-run-step`, `rs-experiment-run-details`, `rs-experiment-run-actions`, `rs-experiment-run-action`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/experiment-run.tsx`
CSS: `packages/core/css/components/experiment-run.css`
---
# Spectrum plot
A supplied numeric spectrum with labelled axes, caller-provided peak annotations and a complete paginated data table.
Category: science
Name: `spectrum-plot`
Also known as: Spectral plot, Spectroscopy chart, Frequency spectrum, Signal spectrum, Peak annotations
Page: https://vlak.dev/components/spectrum-plot/
## When to use
- Display supplied x/y spectra in acquisition order without smoothing, peak detection or resampling.
- Supply axis labels and units; optional finite increasing domains must contain every point and annotation.
- Up to 4096 points and 128 annotations; larger inputs receive a visible limit message without partial plotting.
- Use the 50-row data pages to inspect every supplied point at its original numeric precision.
## When not to
- Interpreting a marked feature as an identified substance or validated scientific finding.
- Using rounded axis tick labels as the original data, or relying on this display for signal processing.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { SpectrumPlot } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add spectrum-plot
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/spectrum-plot.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Supplied spectrum
Supplied numeric data
Wavelength (nm)
Signal (counts)
400
1
500
15
```
## Example
```tsx
import { SpectrumPlot } from "@noorddev/vlak-react";
```
## Props
### SpectrumPlot
A supplied spectrum and peak annotations, with a paginated complete data table.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `points` (required) | `readonly SpectrumPoint[]` | | Up to 4096 supplied points, connected in the supplied order without resampling. |
| `xLabel` (required) | `string` | | |
| `yLabel` (required) | `string` | | |
| `xUnit` | `string` | | |
| `yUnit` | `string` | | |
| `xDomain` | `readonly [number, number]` | | |
| `yDomain` | `readonly [number, number]` | | |
| `peaks` | `readonly SpectrumPeak[]` | `[]` | Up to 128 supplied annotations. The component never detects peaks. |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the plot's scroll region, native data disclosure and enabled pagination controls when open. |
| Arrow keys | Scrolls the focused plot region when it exceeds the available width. |
| Enter, Space | Toggles the focused disclosure or activates the focused page button. |
## Accessibility
- A figure caption names the spectrum. The decorative chart is hidden from assistive technology; exact point values remain in a captioned table.
- Every supplied peak has a numbered marker and a visible textual coordinate description; no peaks are inferred.
- Empty, non-finite or out-of-domain data is explicitly reported. Invalid rows remain visible in the table as unavailable values.
- A single point has a visible marker, and constant axes receive display padding without changing the data.
- Pagination bounds table rendering to 50 rows. Controls have 44px targets, visible focus and a polite row-range announcement.
- The figure ref and native attributes pass through; large data is rejected before scanning or rendering it.
## Classes
`rs-spectrum-plot`, `rs-spectrum-plot-label`, `rs-spectrum-plot-description`, `rs-spectrum-plot-scroll`, `rs-spectrum-plot-svg`, `rs-spectrum-plot-axis`, `rs-spectrum-plot-grid`, `rs-spectrum-plot-trace`, `rs-spectrum-plot-point`, `rs-spectrum-plot-annotation`, `rs-spectrum-plot-ticks`, `rs-spectrum-plot-x-label`, `rs-spectrum-plot-peaks`, `rs-spectrum-plot-summary`, `rs-spectrum-plot-table`, `rs-spectrum-plot-cell`, `rs-spectrum-plot-controls`, `rs-spectrum-plot-button`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/spectrum-plot.tsx`
CSS: `packages/core/css/components/spectrum-plot.css`
---
# Audio meter
Shows supplied channel levels and peaks in decibels, with bounded native meters and explicit missing readings.
Category: creative
Name: `audio-meter`
Also known as: AudioMeter, Level meter, Peak meter, Decibel meter, Channel meter
Page: https://vlak.dev/components/audio-meter/
## When to use
- Live or recorded decibel readings supplied by an audio host.
- min and max to set the visible scale; supplied readings remain visible as text.
- Negative infinity for digital silence, and null for an unavailable level.
## When not to
- Expecting microphone access, audio analysis, or automatic peak holding.
- Treating a missing reading as silence or zero decibels.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { AudioMeter } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add audio-meter
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/audio-meter.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Output
Left-12 dB
-12 dB
Peak: -3 dB
```
## Example
```tsx
import { AudioMeter } from "@noorddev/vlak-react";
```
## Props
### AudioMeter
Supplied channel levels and peaks; no audio analysis or peak holding.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `channels` (required) | `AudioMeterChannel[]` | | |
| `min` | `number` | `-60` | |
| `max` | `number` | `0` | |
## Accessibility
- Each native meter has a channel name, minimum, maximum, and decibel value text.
- Supplied peaks are visible text; absent and invalid readings suppress the meter.
- Native meter styles remove browser gradients so the track and fill remain monochrome. System colors retain visible fill and boundaries in forced colors.
- The ref and native attributes reach the root div.
## Classes
`rs-audio-meter`, `rs-audio-meter-label`, `rs-audio-meter-channel`, `rs-audio-meter-text`, `rs-audio-meter-bar`, `rs-audio-meter-note`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/audio-meter.tsx`
CSS: `packages/core/css/components/audio-meter.css`
---
# Channel strip
Edits channel gain, pan, mute, and solo with native sliders and 44px toggle actions wired to caller-owned state.
Category: creative
Name: `channel-strip`
Also known as: ChannelStrip, Mixer channel, Audio mixer, Gain control, Pan control, Mute solo
Page: https://vlak.dev/components/channel-strip/
## When to use
- A host channel whose gain, pan, mute, and solo states belong together.
- value/defaultValue/onValueChange for controlled or local editing; connect changes to your audio host.
- Pan from -100 percent left through zero center to 100 percent right; gain uses decibels.
## When not to
- Assuming UI changes process audio without a connected host.
- Using solo as a global mixing policy; the application coordinates other channels.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ChannelStrip } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add channel-strip
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/channel-strip.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { ChannelStrip } from "@noorddev/vlak-react";
```
## Props
### ChannelStrip
Gain, pan, mute and solo state for an application-owned audio channel.
Extends `Omit, "onChange" | "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `ChannelStripValue` | | |
| `defaultValue` | `ChannelStripValue` | `initial` | |
| `onValueChange` | `(value: ChannelStripValue) => void` | | |
| `gainMin` | `number` | `-60` | |
| `gainMax` | `number` | `12` | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through enabled gain, pan, mute, and solo controls. |
| Arrow keys, Home, End | Uses native slider stepping and bounds. |
| Enter, Space | Toggles the focused mute or solo action. |
## Accessibility
- A fieldset and legend name the channel; native sliders expose gain and pan bounds and descriptive value text. In-range values retain their supplied precision.
- Vlak Button supplies mute and solo actions with stable names and aria-pressed; their entire surface changes on selection.
- All controls meet the 44px target size. Disabled or read-only controls cannot edit the channel.
- Uncontrolled form reset restores the supplied default; named read-only channels retain all valid values in form submissions. Disabled channels and out-of-range sliders are omitted. The ref reaches the fieldset.
## Classes
`rs-channel-strip`, `rs-channel-strip-label`, `rs-channel-strip-field`, `rs-channel-strip-text`, `rs-channel-strip-range`, `rs-channel-strip-actions`, `rs-channel-strip-button`, `rs-channel-strip-pressed`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/channel-strip.tsx`
CSS: `packages/core/css/components/channel-strip.css`
---
# Parameter knob
Displays a rotary parameter over a native horizontal range input, with named values, units, and a 64px control.
Category: creative
Name: `parameter-knob`
Also known as: ParameterKnob, Rotary control, Dial, Audio knob, Parameter dial
Page: https://vlak.dev/components/parameter-knob/
## When to use
- A compact bounded parameter with an explicit label, step, and unit.
- value/defaultValue/onValueChange and native form attributes; the ref reaches the range input.
- Horizontal pointer movement and the browser's native range keyboard behavior.
## When not to
- Implying circular pointer dragging; the dial is a visual representation of a horizontal range.
- Non-finite values or invalid bounds; they render an unavailable disabled control.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ParameterKnob } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add parameter-knob
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/parameter-knob.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
50%
```
## Example
```tsx
import { ParameterKnob } from "@noorddev/vlak-react";
```
## Props
### ParameterKnob
A rotary display driven by a native horizontal range input.
Extends `Omit, "type" | "value" | "defaultValue" | "onChange" | "min" | "max" | "step">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `number` | | |
| `defaultValue` | `number` | | |
| `onValueChange` | `(value: number) => void` | | |
| `min` | `number` | `0` | |
| `max` | `number` | `100` | |
| `step` | `number` | `1` | |
| `unit` | `string` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the native range input and its visible dial ring. |
| Arrow keys, Home, End | Uses native range stepping and bounds unless read-only. |
## Accessibility
- The native range uses the visible label and exposes min, max, step, and value text including the unit.
- The full 64px dial is the input target; the pointer graphic is decorative.
- Form reset restores uncontrolled defaults and preserves controlled values.
- The ref, native input attributes, className, and style reach the range input.
## Classes
`rs-parameter-knob`, `rs-parameter-knob-label`, `rs-parameter-knob-control`, `rs-parameter-knob-pointer`, `rs-parameter-knob-input`, `rs-parameter-knob-value`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/parameter-knob.tsx`
CSS: `packages/core/css/components/parameter-knob.css`
---
# Timecode field
Edits hours, minutes, seconds, and frames with native form validation for a supplied integer non-drop frame rate.
Category: creative
Name: `timecode-field`
Also known as: TimecodeField, Timecode input, Frame address, In point, Out point, Non-drop timecode
Page: https://vlak.dev/components/timecode-field/
## When to use
- Integer non-drop rates from 1 through 99, supplied explicitly by the application.
- Two-digit hours, minutes, seconds, and frames separated by colons.
- onValueChange receives editable text, including incomplete input; check native validity before committing.
## When not to
- Drop-frame, fractional frame rates, or automatic conversion between timecode standards.
- Coercing invalid frame numbers into a different timestamp without user intent.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { TimecodeField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add timecode-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/timecode-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
24 fps, non-drop. Hours:minutes:seconds:frames.
```
## Example
```tsx
import { TimecodeField } from "@noorddev/vlak-react";
```
## Props
### TimecodeField
Editable hours, minutes, seconds and frames for integer non-drop timecode.
Extends `Omit, "type" | "value" | "defaultValue" | "onChange" | "pattern">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLInputElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `frameRate` (required) | `number` | | Integer non-drop frame rate from 1 to 99. |
| `value` | `string` | | |
| `defaultValue` | `string` | `""` | |
| `onValueChange` | `(value: string) => void` | | Receives editable text, including incomplete or invalid input. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the native text input. |
| Text editing keys | Edits and selects timecode text using native input behavior. |
## Accessibility
- A visible label names the input, and the frame-rate hint or validation error is linked as its description.
- The format pattern and custom validity reject out-of-range frames and unsupported rates; required uses native form validation.
- A 44px input target and focus ring accompany aria-invalid on invalid timecode.
- The ref and native input attributes reach the input; uncontrolled form reset restores the default text.
## Classes
`rs-timecode-field`, `rs-timecode-field-label`, `rs-timecode-field-input`, `rs-timecode-field-hint`
## Dependencies
Registry dependencies: [input](input.md).
React: `packages/react/src/components/timecode-field.tsx`
CSS: `packages/core/css/components/timecode-field.css`
---
# Clip timeline
Positions supplied clips within a declared duration, with contained horizontal scrolling, accessible selection, and optional seeking.
Category: creative
Name: `clip-timeline`
Also known as: ClipTimeline, Video timeline, Audio timeline, Track timeline, Clip selection, Edit timeline
Page: https://vlak.dev/components/clip-timeline/
## When to use
- Caller-owned tracks and clips measured explicitly in seconds or whole frames.
- onSelectClip for selection requests and onSeek for a native position control; update the supplied selectedClipId and position.
- Separate rows within each track keep overlapping clips visible without implying an edit.
## When not to
- Expecting drag editing, playback, trimming, or a media backend.
- Hiding invalid or unassigned clips; their text records remain visible.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ClipTimeline } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add clip-timeline
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/clip-timeline.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Assembly
0 to 60 seconds
Video
Opening
Opening · Video · 6–24 seconds
```
## Example
```tsx
import { ClipTimeline } from "@noorddev/vlak-react";
```
## Props
### ClipTimeline
Supplied clip positions, with separate reachable selection and seek controls.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `tracks` (required) | `ClipTrack[]` | | |
| `clips` (required) | `TimelineClip[]` | | |
| `duration` (required) | `number` | | |
| `unit` (required) | `"seconds" \| "frames"` | | |
| `position` | `number \| null` | | |
| `selectedClipId` | `string \| null` | | |
| `onSeek` | `(position: number) => void` | | |
| `onSelectClip` | `(id: string) => void` | | |
| `disabled` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the optional seek control, scrollable track region, and selection buttons. |
| Arrow keys, Home, End | Uses native seeking on the range input; arrow keys scroll the focused track region. |
| Enter, Space | Requests selection from a focused clip button. |
## Accessibility
- Clip graphics are decorative and accompanied by complete text records with track, start, end, and unit.
- Every selectable clip has a separate 44px button, including clips whose plotted duration is less than one pixel.
- The horizontal viewport remains inside the component and can receive keyboard focus.
- Invalid duration or clip intervals do not produce misleading geometry; the ref and native attributes reach the root div.
## Classes
`rs-clip-timeline`, `rs-clip-timeline-label`, `rs-clip-timeline-note`, `rs-clip-timeline-seek`, `rs-clip-timeline-range`, `rs-clip-timeline-viewport`, `rs-clip-timeline-track`, `rs-clip-timeline-clips`, `rs-clip-timeline-lane`, `rs-clip-timeline-clip`, `rs-clip-timeline-selected`, `rs-clip-timeline-rows`, `rs-clip-timeline-button`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/clip-timeline.tsx`
CSS: `packages/core/css/components/clip-timeline.css`
---
# Render queue
Displays supplied export jobs, progress, and status with explicit cancel and retry callbacks for a connected renderer.
Category: creative
Name: `render-queue`
Also known as: RenderQueue, Export queue, Encoding queue, Render jobs, Export progress
Page: https://vlak.dev/components/render-queue/
## When to use
- Renderer-owned jobs with queued, rendering, complete, failed, or canceled status.
- onCancel for active jobs and onRetry for failed or canceled jobs; the host owns the resulting status.
- Known percentages from zero through 100; missing progress remains explicitly unreported.
## When not to
- Simulating render progress or success without a backend result.
- Displaying cancel or retry controls when there is no callback to handle them.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { RenderQueue } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add render-queue
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/render-queue.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Exports
Film masterRendering
42%
```
## Example
```tsx
import { RenderQueue } from "@noorddev/vlak-react";
```
## Props
### RenderQueue
Host-owned render jobs and available cancel or retry actions.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `jobs` (required) | `RenderJob[]` | | |
| `onCancel` | `(id: string) => void` | | |
| `onRetry` | `(id: string) => void` | | |
| `disabled` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through available cancel and retry buttons. |
| Enter, Space | Requests the focused job action without changing the supplied job state. |
## Accessibility
- Job labels and statuses remain text; determinate native progress is named per job.
- Missing or invalid progress has an explicit text state and never emits NaN or an invented percentage.
- Actions have job-specific names, 44px targets, and disabled support.
- The ref and native attributes reach the root div.
## Classes
`rs-render-queue`, `rs-render-queue-label`, `rs-render-queue-list`, `rs-render-queue-job`, `rs-render-queue-header`, `rs-render-queue-note`, `rs-render-queue-progress`, `rs-render-queue-action`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/render-queue.tsx`
CSS: `packages/core/css/components/render-queue.css`
---
# Layer stack
Manages supplied layer selection, visibility, locking, and order through named 44px controls and caller-owned changes.
Category: creative
Name: `layer-stack`
Also known as: LayerStack, Layers panel, Layer list, Layer inspector, Object stack
Page: https://vlak.dev/components/layer-stack/
## When to use
- Top-to-bottom layer order for a graphics, audio, or video editor.
- onLayersChange receives the proposed array; the application applies it and owns persistence.
- onSelect independently controls selection; locked layers cannot use their move actions.
## When not to
- Implying drag-and-drop support or modifying document content behind the host's back.
- Rendering state-changing controls without onLayersChange.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { LayerStack } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add layer-stack
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/layer-stack.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Layers
TitleVisible · Unlocked
BackgroundVisible · Locked
```
## Example
```tsx
import { useState } from "react";
import { LayerStack } from "@noorddev/vlak-react";
import type { CreativeLayer } from "@noorddev/vlak-react";
function Layers() {
const [layers, setLayers] = useState([{ id: "title", label: "Title", visible: true, locked: false }, { id: "background", label: "Background", visible: true, locked: true }]);
const [selected, setSelected] = useState(null);
return ;
}
```
## Props
### LayerStack
A controlled layer order with explicit selection, visibility, lock and move actions.
Extends `Omit, "onSelect">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `layers` (required) | `CreativeLayer[]` | | Ordered from top to bottom. |
| `selectedId` | `string \| null` | | |
| `onSelect` | `(id: string) => void` | | |
| `onLayersChange` | `(layers: CreativeLayer[]) => void` | | |
| `disabled` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through available layer selection and Vlak visibility, lock, and move buttons. |
| Enter, Space | Requests the focused action; move buttons reorder one position when allowed. |
## Accessibility
- An ordered list preserves the supplied layer order, with visible status text for visibility and locking.
- Selection, visibility, and lock controls have stable names and pressed states.
- Move actions name their layer, disable at boundaries or when locked, and avoid a drag-only workflow.
- All actions have 44px targets; the ref and native attributes reach the root div.
## Classes
`rs-layer-stack`, `rs-layer-stack-label`, `rs-layer-stack-list`, `rs-layer-stack-row`, `rs-layer-stack-actions`, `rs-layer-stack-action`, `rs-layer-stack-button`, `rs-layer-stack-selected`, `rs-layer-stack-note`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/layer-stack.tsx`
CSS: `packages/core/css/components/layer-stack.css`
---
# Color inspector
Edits a six-digit hex color and alpha with a data-driven preview, a transparency ground, and native form validation.
Category: creative
Name: `color-inspector`
Also known as: ColorInspector, Color input, Hex editor, Alpha control, Fill inspector, Color swatch
Page: https://vlak.dev/components/color-inspector/
## When to use
- Application-owned color data; only the swatch uses the supplied hue, while the inspector shell stays monochrome.
- Six-digit hex including #, with alpha from zero transparent to one opaque.
- onValueChange receives editable input; incomplete alpha is null and invalid hex remains available for correction.
## When not to
- Assuming color-space conversion, gamut checking, contrast certification, or color-profile management.
- Presenting a valid preview when the supplied color or alpha is invalid.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ColorInspector } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add color-inspector
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/color-inspector.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { ColorInspector } from "@noorddev/vlak-react";
```
## Props
### ColorInspector
A data swatch and editable six-digit hex and alpha, on a monochrome shell.
Extends `Omit, "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `InspectorColor` | | |
| `defaultValue` | `InspectorColor` | `initial` | |
| `onValueChange` | `(value: InspectorColor) => void` | | Receives editable hex text and alpha, including incomplete values. |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between the native hex and alpha inputs. |
| Text editing keys | Edits or selects hex and alpha values; any alpha precision from 0 to 1 is accepted. |
## Accessibility
- A fieldset and legend name the color; hex and alpha are labelled native controls with 44px targets.
- The decorative swatch has an explicit text equivalent and preserves caller-owned color in forced colors.
- Pattern, required, and numeric bounds supply native form validation; invalid data suppresses the swatch.
- Controlled and uncontrolled values support form reset; the ref and native attributes reach the fieldset.
## Classes
`rs-color-inspector`, `rs-color-inspector-label`, `rs-color-inspector-preview`, `rs-color-inspector-swatch`, `rs-color-inspector-fields`, `rs-color-inspector-field`, `rs-color-inspector-input`, `rs-color-inspector-note`
## Dependencies
Registry dependencies: [input](input.md).
React: `packages/react/src/components/color-inspector.tsx`
CSS: `packages/core/css/components/color-inspector.css`
---
# Spacing control
Edits top, right, bottom, and left spacing with linked or independent native number fields and explicit units.
Category: creative
Name: `spacing-control`
Also known as: SpacingControl, Spacing inspector, Padding editor, Margin editor, Inset controls, Box model
Page: https://vlak.dev/components/spacing-control/
## When to use
- Padding, margin, inset, or other four-sided numeric values in a caller-specified unit.
- Link sides to apply the next edit to every side; linking alone preserves existing values.
- value/defaultValue/onValueChange and linked/defaultLinked/onLinkedChange control the values and link state independently.
## When not to
- Converting between units or assuming CSS semantics beyond the supplied numeric fields.
- Treating cleared values as zero; a cleared side is null.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { SpacingControl } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add spacing-control
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/spacing-control.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { SpacingControl } from "@noorddev/vlak-react";
```
## Props
### SpacingControl
Four native numeric fields; linking applies the next edit to every side.
Extends `Omit, "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `value` | `SpacingValue` | | |
| `defaultValue` | `SpacingValue` | `initial` | |
| `onValueChange` | `(value: SpacingValue) => void` | | |
| `linked` | `boolean` | | |
| `defaultLinked` | `boolean` | `false` | |
| `onLinkedChange` | `(linked: boolean) => void` | | |
| `unit` | `string` | `"px"` | |
| `min` | `number` | | |
| `max` | `number` | | |
| `step` | `number` | `1` | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through four number inputs and the link action. |
| Arrow up, Arrow down | Uses native number stepping with supplied min, max, and step. |
| Enter, Space | Toggles Link sides on the focused action. |
## Accessibility
- A fieldset and legend name the spacing group; each native number field includes its side and unit.
- Link sides has a stable name and aria-pressed, plus text explaining the next-edit behavior.
- Inputs and the link action have 44px targets; native bounds and step support form validation.
- Named fields submit separately; reset restores uncontrolled values and link state. The ref reaches the fieldset.
## Classes
`rs-spacing-control`, `rs-spacing-control-label`, `rs-spacing-control-fields`, `rs-spacing-control-field`, `rs-spacing-control-input`, `rs-spacing-control-link`, `rs-spacing-control-linked`, `rs-spacing-control-note`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md).
React: `packages/react/src/components/spacing-control.tsx`
CSS: `packages/core/css/components/spacing-control.css`
---
# Coordinate reference field
Two or three numeric coordinate axes with supplied units and a reference selector that preserves entered values when assigning a reference.
Category: geospatial
Name: `coordinate-reference-field`
Also known as: Coordinate input, Reference system selector, Survey point field, Projected coordinate, Latitude longitude field
Page: https://vlak.dev/components/coordinate-reference-field/
## When to use
- Survey points and imported coordinates whose reference, axis order and units are supplied by the application.
- Supply two or three axes in coordinate order with unique, non-empty identifiers; reference values must also be unique and non-empty.
- Use value and onValueChange for application-owned conversion. Changing the reference requests only a new identifier and preserves the numeric coordinates.
- name submits reference as name.reference and each axis as name.coordinates followed by its identifier. null represents a missing coordinate or reference.
## When not to
- Inferring a reference from numeric ranges, treating a reference assignment as reprojection or guessing axis units.
- Using a latitude or longitude bound for a projected axis unless the application supplies that constraint.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CoordinateReferenceField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add coordinate-reference-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/coordinate-reference-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Assigning a reference keeps the entered coordinates.
Coordinate reference
```
## Example
```tsx
import { CoordinateReferenceField } from "@noorddev/vlak-react";
```
## Props
### CoordinateReferenceField
Numeric coordinates and an explicitly assigned reference, without implicit conversion.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `axes` (required) | `readonly CoordinateReferenceAxis[]` | | Two or three axes in the supplied coordinate order. Units are never inferred. |
| `references` (required) | `readonly CoordinateReferenceOption[]` | | |
| `value` | `CoordinateReferenceValue` | | |
| `defaultValue` | `CoordinateReferenceValue` | `initial` | |
| `onValueChange` | `(value: CoordinateReferenceValue) => void` | | Assigning a reference preserves every numeric value. The host owns reprojection. |
| `description` | `ReactNode` | | |
| `referenceLabel` | `string` | `"Coordinate reference"` | |
| `unknownReferenceLabel` | `string` | `"Unknown reference"` | |
| `required` | `boolean` | | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the reference selector and coordinate inputs in supplied axis order. |
| Arrow keys, Home, End | Opens and navigates the Vlak selector. Enter or Space chooses a reference without converting numeric values; Escape closes the menu. |
| Typing | Edits numeric coordinates using the native number inputs. |
## Accessibility
- The fieldset legend names the coordinate group. Vlak Select and Input provide shared control paint; every numeric input has a visible axis label, supplied unit and 44px target.
- Unknown references, missing coordinates and non-finite numbers have explicit text. Zero is retained. Invalid supplied values participate in native form validation.
- Required and supplied axis bounds use native validation. No geographic constraints are inferred.
- Uncontrolled values follow native form reset, including external forms; controlled values remain with the application.
- Read-only valid values still submit. Disabled fields do not submit. The fieldset ref, native attributes, className and style pass through.
## Classes
`rs-coordinate-reference-field`, `rs-coordinate-reference-field-legend`, `rs-coordinate-reference-field-axes`, `rs-coordinate-reference-field-label`, `rs-coordinate-reference-field-control`, `rs-coordinate-reference-field-note`
## Dependencies
Registry dependencies: [select](select.md), [input](input.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/coordinate-reference-field.tsx`
CSS: `packages/core/css/components/coordinate-reference-field.css`
---
# Datum transform picker
A Vlak transformation selector with source and destination references, supplied accuracy and area, and visible support-grid availability.
Category: geospatial
Name: `datum-transform-picker`
Also known as: Datum transformation, Coordinate operation, Projection operation picker, Support grid selector, Reprojection choice
Page: https://vlak.dev/components/datum-transform-picker/
## When to use
- Comparing operations supplied by a projection engine or survey provider before the application transforms coordinates.
- Supply unique, non-empty operation identifiers and explicit available values. false or null disables an operation; listed grids must all be available.
- Use an empty grids array to state that no support grids are required. Omit grids when the requirements were not supplied.
- null means no operation selected. Unknown current identifiers stay visible as unavailable. The application owns candidate generation, accuracy, compatibility and persistence.
## When not to
- Automatically picking the smallest reported error, assuming an unlisted grid is installed or silently falling back to a different operation.
- Presenting illustrative accuracy or area labels as calculated guarantees.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { DatumTransformPicker } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add datum-transform-picker
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/datum-transform-picker.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Source reference
Site grid
Destination reference
Project grid
Transformation
Parameter transform · Selected
Available
Reported accuracy
1.5 m
Area of use
Project extent
Support grids: None required
```
## Example
```tsx
import { DatumTransformPicker } from "@noorddev/vlak-react";
```
## Props
### DatumTransformPicker
Compares host-supplied operations and keeps unavailable alternatives visible.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `sourceReference` (required) | `ReactNode` | | |
| `destinationReference` (required) | `ReactNode` | | |
| `transformations` (required) | `readonly DatumTransformation[]` | | |
| `value` | `string \| null` | | null means no operation selected; an unknown identifier stays explicitly unavailable. |
| `defaultValue` | `string \| null` | `null` | |
| `onValueChange` | `(value: string \| null) => void` | | |
| `description` | `ReactNode` | | |
| `selectionLabel` | `string` | `"Transformation"` | |
| `noneLabel` | `string` | `"No transformation selected"` | |
| `required` | `boolean` | | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the Vlak transformation selector. |
| Arrow keys, Home, End | Navigates the Vlak selector. Enter or Space chooses an available operation or the no-selection option; Escape closes the menu. Unavailable alternatives are skipped. |
## Accessibility
- Source and destination references have visible labels; null references are explicitly unknown.
- Every candidate retains visible accuracy, area, grid requirements and availability text, including disabled alternatives.
- The selected candidate uses a full-surface fill and a visible Selected label; forced colors retain a distinct border.
- A currently unavailable operation is marked invalid and fails native validation. Required selection uses the native required attribute.
- Vlak Select supplies the 44px trigger, menu, disabled choices and native form value. Read-only valid selections submit through a hidden value; disabled selections do not submit.
- Uncontrolled state follows native form reset, including external forms. Controlled state, native fieldset attributes, ref and consumer styles remain with the caller.
## Classes
`rs-datum-transform-picker`, `rs-datum-transform-picker-legend`, `rs-datum-transform-picker-context`, `rs-datum-transform-picker-term`, `rs-datum-transform-picker-detail`, `rs-datum-transform-picker-label`, `rs-datum-transform-picker-control`, `rs-datum-transform-picker-list`, `rs-datum-transform-picker-item`, `rs-datum-transform-picker-selected`, `rs-datum-transform-picker-title`, `rs-datum-transform-picker-note`
## Dependencies
Registry dependencies: [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/datum-transform-picker.tsx`
CSS: `packages/core/css/components/datum-transform-picker.css`
---
# Raster band mixer
A raster configuration editor with source-band mapping, single or three-channel modes, supplied stretch bounds and explicit missing-data metadata.
Category: geospatial
Name: `raster-band-mixer`
Also known as: Band composition, Multiband raster, Satellite band selector, Raster stretch, Single-band renderer settings
Page: https://vlak.dev/components/raster-band-mixer/
## When to use
- Mapping supplied raster bands to red, green and blue display channels or a single band.
- Choose no enhancement, stretch, clipping or both. Each active channel keeps its own supplied minimum and maximum; band changes do not calculate new ranges.
- Use unique, non-empty band identifiers. noDataValue undefined means unknown, null means no sentinel, and zero remains a supplied missing-data value.
- The name prefix submits mode, stretch and active channel fields such as name.red.band and name.red.minimum. Inactive mappings remain in state but do not submit; ranges only submit when enhancement uses them.
## When not to
- Treating the component as a raster renderer, deriving a histogram or assuming a missing-data value from the image appearance.
- Reusing display ranges across different bands without application review. No automatic statistics or unit conversion runs here.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { RasterBandMixer } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add raster-band-mixer
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/raster-band-mixer.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
The application renders the image from this configuration.
Rendering mode
Range treatment
Single band
Single band source
Missing-data value: 0. Unit: counts
```
## Example
```tsx
import { RasterBandMixer } from "@noorddev/vlak-react";
import type { RasterBandConfiguration } from "@noorddev/vlak-react";
const configuration: RasterBandConfiguration = {
mode: "rgb", stretch: "none",
red: { bandId: "b3", minimum: 0, maximum: 255 },
green: { bandId: "b2", minimum: 0, maximum: 255 },
blue: { bandId: "b1", minimum: 0, maximum: 255 },
single: { bandId: "b1", minimum: 0, maximum: 255 },
};
```
## Props
### RasterBandMixer
Selects source bands and display ranges. No pixels, statistics or missing-data rules are inferred.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `bands` (required) | `readonly RasterSourceBand[]` | | |
| `value` | `RasterBandConfiguration` | | |
| `defaultValue` | `RasterBandConfiguration` | `initial` | |
| `onValueChange` | `(value: RasterBandConfiguration) => void` | | Emits configuration only. The host owns rendering and any statistics or range calculation. |
| `description` | `ReactNode` | | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through mode, range treatment and active channel controls. |
| Arrow keys, Home, End | Navigates the focused Vlak selector. Enter or Space commits a choice; Escape closes the menu. |
| Typing | Edits each active channel's numeric range bounds. |
## Accessibility
- A fieldset legend names the editor. Vlak Select and Input provide shared control paint, with channel labels and 44px targets.
- Missing, unavailable and disabled source bands stay distinct. Missing-data values and units are readable text, with zero preserved.
- Active channels require a band. Enhancement requires finite bounds with minimum less than maximum; invalid configurations fail native form validation.
- Switching modes preserves inactive mappings without submitting them. No enhancement hides and omits range fields without discarding their values.
- Native form reset restores uncontrolled defaults, including external forms; controlled updates remain with the application.
- Read-only valid configuration values submit; disabled fields do not. Native fieldset attributes, ref, className and style pass through.
## Classes
`rs-raster-band-mixer`, `rs-raster-band-mixer-legend`, `rs-raster-band-mixer-fields`, `rs-raster-band-mixer-channel`, `rs-raster-band-mixer-title`, `rs-raster-band-mixer-label`, `rs-raster-band-mixer-control`, `rs-raster-band-mixer-note`
## Dependencies
Registry dependencies: [select](select.md), [input](input.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/raster-band-mixer.tsx`
CSS: `packages/core/css/components/raster-band-mixer.css`
---
# Stage position list
Reviews supplied named stage positions with an explicit coordinate frame, per-axis units, inclusion state and controlled selection, reorder and removal requests.
Category: science
Name: `stage-position-list`
Also known as: stage positions, position list, microscopy positions, multi-position acquisition, waypoint list
Page: https://vlak.dev/components/stage-position-list/
## When to use
- Reviewing a microscopy stage-position plan with explicit frame identity, supplied coordinates and per-axis units.
- Selection requires value and onValueChange; there is no uncontrolled selection. Inclusion, order and removal are controlled requests. The host supplies accepted records; no optimistic edits or instrument commands occur.
- Names may repeat; immutable unique IDs distinguish rows and actions. At most 128 positions are rendered. Invalid identifiers or excess records produce an explicit unavailable state.
- Missing coordinates show Not supplied; nonfinite coordinates show Unavailable. Zero, negative zero and signed finite values retain their supplied representation. Missing frame or units stay explicit.
- readOnly locks record edits while inspection selection remains available. pending locks edits to a record and swaps across it. disabled uses a native fieldset and locks every control.
- An optional name submits the selected record ID; form associates the selection with an external form. Coordinates and inclusion records remain host-owned data. Controlled values survive native form reset.
## When not to
- Moving a stage, calculating travel, transforming coordinate frames or converting physical units.
- Treating selection as an instrument position, missing coordinates as zero, or an edit request as an accepted plan.
- Large position inventories that need pagination or virtualization; use a bounded window instead.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { StagePositionList } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add stage-position-list
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/stage-position-list.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Coordinate frame: Recorded stage (stage-01)
Overview (field-01)
X (µm)
0
Y (µm)
-12.5
Z (µm)
Not supplied
Included in plan
```
## Example
```tsx
import { useState } from "react";
import { StagePositionList } from "@noorddev/vlak-react";
import type { StagePosition } from "@noorddev/vlak-react";
export function PositionPlan() {
const [positions, setPositions] = useState([
{ id: "field-01", name: "Overview", x: 0, y: -12.5, z: null, enabled: true },
{ id: "field-02", name: "Edge detail", x: 120.25, y: 36, z: 0, enabled: false },
]);
const [selected, setSelected] = useState(null);
return setPositions(current => current.map(position => position.id === id ? { ...position, enabled } : position))}
onOrderChange={ids => setPositions(current => ids.map(id => current.find(position => position.id === id)!))}
onRemove={id => { setPositions(current => current.filter(position => position.id !== id)); if (selected === id) setSelected(null); }}
/>;
}
```
## Props
### StagePositionList
Supplied stage coordinates and controlled plan edits. No stage motion or coordinate conversion occurs.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `coordinateFrame` (required) | `StageCoordinateFrame \| null` | | |
| `units` (required) | `StagePositionUnits` | | |
| `positions` (required) | `readonly StagePosition[]` | | |
| `value` | `string \| null` | `null` | Controlled selected record identifier; pair with onValueChange for inspection. Missing or unknown identifiers never select a fallback. |
| `onValueChange` | `(id: string) => void` | | |
| `onEnabledChange` | `(id: string, enabled: boolean) => void` | | |
| `onOrderChange` | `(ids: readonly string[]) => void` | | Requests an order of existing identifiers without changing records. |
| `onRemove` | `(id: string) => void` | | |
| `description` | `ReactNode` | | |
| `readOnly` | `boolean` | `false` | Prevents record edits; inspection selection remains available. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab, Shift+Tab | Moves between the native radio group, inclusion checkboxes and enabled move/remove buttons. |
| Arrow keys | Changes the focused native radio selection and requests its record ID; the host controls the accepted selection. |
| Space | Selects a focused radio or requests a focused inclusion checkbox change. |
| Enter, Space | Activates a move or remove button. Reorder focus follows the same ID; accepted removal focuses an adjacent surviving row or the empty fieldset without stealing focus from elsewhere. |
## Accessibility
- A fieldset legend names the position list; frame context, selection status and optional host descriptions are associated with it.
- Native radios, checkboxes and buttons retain keyboard behavior, visible focus and at least 44px targets. Coordinates use a labelled definition list with explicit axis units.
- Visible immutable IDs keep repeated names distinguishable. Unknown selected IDs leave every radio unselected and produce an explicit message.
- A polite announcement reports only host-accepted reorder or removal, not the initial request. Pending and inclusion states have text equivalents.
- The fieldset ref and native attributes pass through; className, style, children and aria-describedby merge with component context.
- Logical spacing, wrapping actions and bounded coordinate columns support narrow layouts. Forced-colors styling preserves native control states and focus.
## Classes
`rs-stage-position-list`, `rs-stage-position-list-legend`, `rs-stage-position-list-copy`, `rs-stage-position-list-items`, `rs-stage-position-list-row`, `rs-stage-position-list-selected`, `rs-stage-position-list-head`, `rs-stage-position-list-identity`, `rs-stage-position-list-coordinates`, `rs-stage-position-list-coordinate`, `rs-stage-position-list-axis`, `rs-stage-position-list-number`, `rs-stage-position-list-actions`, `rs-stage-position-list-action`, `rs-stage-position-list-status`
## Dependencies
Registry dependencies: [button](button.md), [checkbox](checkbox.md), [radio](radio.md).
React: `packages/react/src/components/stage-position-list.tsx`
CSS: `packages/core/css/components/stage-position-list.css`
---
# Stack navigator
Navigates supplied depth, time, channel and stage-position axes while preserving exact physical readings and indexed positions.
Category: science
Name: `stack-navigator`
Also known as: Image stack controls, Z-stack navigator, Microscopy axes, Multidimensional image navigator, Stage position selector
Page: https://vlak.dev/components/stack-navigator/
## When to use
- Image stacks with explicit axis labels, sampled physical values and known position indexes.
- Selection values are zero-based indexes; displayed position counts are one-based. Physical values are never calculated from spacing.
- name submits one selected index per axis. Controlled values remain caller-owned; native form reset restores uncontrolled defaults.
## When not to
- Calling an instrument, calculating stage motion, or inferring positions from an index.
- More than 8 axes or 8192 total positions; the component reports the bound rather than truncating axes.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { StackNavigator } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add stack-navigator
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/stack-navigator.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Depth
Position 1 of 3; -1 µm
```
## Example
```tsx
import { StackNavigator } from "@noorddev/vlak-react";
```
## Props
### StackNavigator
Navigates supplied stack coordinates without calculating stage positions or calling an instrument.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `axes` (required) | `readonly StackAxis[]` | | |
| `value` | `Readonly>` | | |
| `defaultValue` | `Readonly>` | `{}` | |
| `onValueChange` | `(value: StackSelection) => void` | | |
| `description` | `ReactNode` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between enabled previous, position-select and next controls. |
| Arrow keys, Home, End, typing | Opens and navigates the position list; disabled positions are skipped. |
| Enter, Space | Confirms the active list option or activates the focused previous or next button. |
| Escape | Closes the position list without changing selection. |
## Accessibility
- Every axis has a visible select label and a text description containing the exact displayed index and physical value.
- Zero and negative physical positions remain visible. Missing or invalid readings are explicitly unavailable.
- Each input and button has a 44px target and visible focus; no axis is selected implicitly.
- Read-only values remain submitted through hidden fields, while disabled fieldsets do not submit.
- The fieldset ref, form association, native attributes, className and style pass through.
- The shared Select and Button primitives supply combobox navigation and control styling; native form values remain available through the Select backing control.
## Classes
`rs-stack-navigator`, `rs-stack-navigator-legend`, `rs-stack-navigator-axis`, `rs-stack-navigator-label`, `rs-stack-navigator-row`, `rs-stack-navigator-step`, `rs-stack-navigator-copy`
## Dependencies
Registry dependencies: [button](button.md), [select](select.md).
React: `packages/react/src/components/stack-navigator.tsx`
CSS: `packages/core/css/components/stack-navigator.css`
---
# Acquisition sequencer
Edits supplied capture steps, exact exposure, time, depth and channel values, and distinguishes requested actions from recorded run state.
Category: science
Name: `acquisition-sequencer`
Also known as: Capture sequence, Microscopy acquisition plan, Time-lapse plan, Capture step editor, Instrument run plan
Page: https://vlak.dev/components/acquisition-sequencer/
## When to use
- Editing and reordering an existing capture plan with onStepsChange.
- Pass exact values and units from the acquisition application; the component performs no conversions or scheduling.
- Use explicit step actions and onAction to request operations. Supply pending and confirmedLabel from actual host state.
## When not to
- Treating an edit or action callback as proof that capture ran successfully.
- Deriving instrument settings or executing acquisition. The host owns commands, persistence and confirmations.
- More than 128 steps or 128 channels.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { AcquisitionSequencer } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add acquisition-sequencer
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/acquisition-sequencer.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
First planeNot run
Exposure 10 ms · Time offset 0 s · Depth -1 µm · Phase
```
## Example
```tsx
import { useState } from "react";
import { AcquisitionSequencer } from "@noorddev/vlak-react";
import type { AcquisitionStep } from "@noorddev/vlak-react";
function CapturePlan() {
const [steps, setSteps] = useState([
{ id: "first", label: "First plane", exposure: 10, exposureUnit: "ms", time: 0, timeUnit: "s", depth: -1, depthUnit: "µm", channel: "phase", status: "Not run" },
{ id: "second", label: "Second plane", exposure: 10, exposureUnit: "ms", time: 5, timeUnit: "s", depth: 0, depthUnit: "µm", channel: "phase", status: "Not run" },
]);
return ;
}
```
## Props
### AcquisitionSequencer
A controlled capture plan editor and recorded-state display, without an acquisition engine.
Extends `FieldsetHTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `steps` (required) | `readonly AcquisitionStep[]` | | |
| `channels` (required) | `readonly AcquisitionChannel[]` | | |
| `onStepsChange` | `(steps: readonly AcquisitionStep[]) => void` | | |
| `onAction` | `(stepId: string, actionId: string) => void` | | |
| `description` | `ReactNode` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through enabled numeric inputs, channel selectors and step actions. |
| Arrow keys, Home, End, typing | Edits native numeric fields or navigates the opened channel list. |
| Enter, Space | Confirms the active channel option or requests the focused action or reorder. |
| Escape | Closes the channel list without changing the supplied selection. |
## Accessibility
- Step fields and action names include the step number and label, preventing ambiguity between repeated capture names.
- Exposure and time offsets use a native non-negative minimum; signed depth values and all supplied units are preserved.
- Pending steps disable editing and actions while their last recorded state remains visible.
- Controls have 44px targets. Controlled native inputs retain the supplied plan through form resets.
- The fieldset ref and native attributes pass through; no callback is interpreted as an actual run confirmation.
- Generic controls compose the shared Input, Select and Button primitives; the native numeric fields and Select backing control preserve form values.
## Classes
`rs-acquisition-sequencer`, `rs-acquisition-sequencer-legend`, `rs-acquisition-sequencer-list`, `rs-acquisition-sequencer-step`, `rs-acquisition-sequencer-head`, `rs-acquisition-sequencer-title`, `rs-acquisition-sequencer-fields`, `rs-acquisition-sequencer-label`, `rs-acquisition-sequencer-control`, `rs-acquisition-sequencer-value`, `rs-acquisition-sequencer-copy`, `rs-acquisition-sequencer-actions`, `rs-acquisition-sequencer-action`
## Dependencies
Registry dependencies: [button](button.md), [input](input.md), [select](select.md).
React: `packages/react/src/components/acquisition-sequencer.tsx`
CSS: `packages/core/css/components/acquisition-sequencer.css`
---
# Sequence alignment
Displays a bounded window of already aligned reference and read strings, with supplied genomic positions, gaps and keyboard region selection.
Category: science
Name: `sequence-alignment`
Also known as: Aligned sequence viewer, Read alignment window, Genomic alignment, Base selection, Sequence window
Page: https://vlak.dev/components/sequence-alignment/
## When to use
- Inspecting up to 120 pre-aligned columns and 32 reads with explicit reference and read labels.
- Supply one one-based genomic position per aligned column; null represents a reference gap.
- Selection uses one-based aligned column indexes, which are distinct from genomic positions. Use value and onValueChange for host-owned selection.
## When not to
- Running an alignment algorithm or inferring mismatches, insertions, variant calls or genomic positions.
- Passing inconsistent sequence lengths or silently clipping longer alignments. Supply the intended window.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { SequenceAlignment } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add sequence-alignment
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/sequence-alignment.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Read alignment
chr7 · 1-based reference positions; aligned columns include gaps
Reference position
101
102
Reference
A
C
```
## Example
```tsx
import { SequenceAlignment } from "@noorddev/vlak-react";
```
## Props
### SequenceAlignment
A bounded window of already aligned strings; reference positions and gaps are caller-supplied.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `contig` (required) | `string` | | |
| `referenceLabel` (required) | `string` | | |
| `referenceSequence` (required) | `string` | | |
| `positions` (required) | `readonly (number \| null)[]` | | One supplied one-based reference position per column; null means a reference gap. |
| `reads` (required) | `readonly AlignedRead[]` | | |
| `value` | `AlignmentSelection \| null` | | |
| `defaultValue` | `AlignmentSelection \| null` | `null` | |
| `onValueChange` | `(value: AlignmentSelection \| null) => void` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Enters the column controls at one focus stop and then reaches the selection actions. |
| Arrow keys, Home, End | Moves focus between columns in sequence order without changing selection. |
| Shift+Arrow keys | Extends the selected column region from its anchor. |
| Enter, Space | Selects the focused base column or activates a selection action. |
## Accessibility
- A native table supplies row labels and reference-position column headers; every base and gap remains visible text.
- Column buttons have 44px targets and full-column selected fills, with aria-pressed and explicit coordinate names.
- Long windows scroll inside their container. Read-only tables provide a focusable scroll region.
- The selection summary lists supplied positions, including gaps, without inventing genomic coordinates.
- The root div forwards its ref and native attributes; inconsistent or oversized windows have explicit unavailable states.
- Selection actions compose the shared Button primitive; the aligned column controls retain their dedicated table interaction.
## Classes
`rs-sequence-alignment`, `rs-sequence-alignment-title`, `rs-sequence-alignment-copy`, `rs-sequence-alignment-scroll`, `rs-sequence-alignment-table`, `rs-sequence-alignment-heading`, `rs-sequence-alignment-control`, `rs-sequence-alignment-actions`, `rs-sequence-alignment-action`, `rs-sequence-alignment-column`, `rs-sequence-alignment-selected`, `rs-sequence-alignment-base`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/sequence-alignment.tsx`
CSS: `packages/core/css/components/sequence-alignment.css`
---
# Coverage inspector
Shows supplied per-locus depth, base and strand counts with an exact position selector, bounded plot and complete depth table.
Category: science
Name: `coverage-inspector`
Also known as: Read depth inspector, Per-base coverage, Strand count inspector, Locus coverage, Genomic depth plot
Page: https://vlak.dev/components/coverage-inspector/
## When to use
- A bounded window of up to 512 unique one-based loci with caller-supplied counts.
- Inspect base and strand counts independently; the component does not sum them or reconcile them with depth.
- Use null for missing counts. Zero means an explicitly recorded count of zero.
## When not to
- Calling variants, assigning significance, or applying coverage thresholds.
- Treating absent counts as zero, or supplying fractional and negative counts as valid depth.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CoverageInspector } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add coverage-inspector
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/coverage-inspector.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Coverage window
chr7 · 1-based positions
Inspect position
Depth
0
```
## Example
```tsx
import { CoverageInspector } from "@noorddev/vlak-react";
```
## Props
### CoverageInspector
Supplied coverage and counts, with missing depth distinct from recorded zero and no variant calls.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `contig` (required) | `string` | | |
| `reference` | `string` | | |
| `loci` (required) | `readonly CoverageLocus[]` | | |
| `value` | `number \| null` | | A supplied one-based position, not an array index. |
| `defaultValue` | `number \| null` | | |
| `onValueChange` | `(position: number \| null) => void` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the Vlak position selector and native depth-table disclosure. |
| Arrow keys, typing | Opens and navigates the Vlak position selector by arrow keys and typeahead. Escape closes its menu. |
| Enter, Space | Chooses a highlighted locus or opens and closes the focused native depth disclosure. |
## Accessibility
- The decorative plot has a complete visible depth table; open markers distinguish unavailable depth from recorded zero.
- Vlak Select provides a 44px trigger and listbox for exact supplied genomic positions. Selected depth, base and strand counts use description lists.
- Non-finite, negative and non-integer counts are unavailable; missing counts are explicitly not supplied.
- At most 16 base symbols are displayed per selected locus. Invalid or oversized locus windows are reported without truncation.
- The figure ref and native attributes pass through; selection supports controlled values and native form reset.
## Classes
`rs-coverage-inspector`, `rs-coverage-inspector-title`, `rs-coverage-inspector-copy`, `rs-coverage-inspector-plot`, `rs-coverage-inspector-stem`, `rs-coverage-inspector-point`, `rs-coverage-inspector-missing`, `rs-coverage-inspector-axis`, `rs-coverage-inspector-label`, `rs-coverage-inspector-select`, `rs-coverage-inspector-counts`, `rs-coverage-inspector-value`, `rs-coverage-inspector-summary`, `rs-coverage-inspector-table`, `rs-coverage-inspector-cell`
## Dependencies
Registry dependencies: [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/coverage-inspector.tsx`
CSS: `packages/core/css/components/coverage-inspector.css`
---
# Genomic region field
Collects a reference, contig and validated integer interval with an explicit one-based inclusive coordinate convention and native form submission.
Category: science
Name: `genomic-region-field`
Also known as: Genome interval input, Genomic coordinates, Contig region input, One-based interval, Genomic location field
Page: https://vlak.dev/components/genomic-region-field/
## When to use
- Integer genomic intervals against a fixed caller-supplied reference and explicit contig lengths.
- The field always uses one-based inclusive positions, including both endpoints. A one-position region has equal start and end.
- name prefixes submitted reference, coordinates, contig, start and end fields. Native form reset restores uncontrolled defaults.
- Changing contig keeps the entered integers and revalidates its bounds; no coordinate conversion occurs.
## When not to
- Silently converting zero-based half-open intervals or moving coordinates between genome assemblies.
- Using guessed contig lengths or clamping invalid coordinates into a different region.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { GenomicRegionField } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add genomic-region-field
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/genomic-region-field.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Reference: Example reference
1-based, inclusive. Both start and end are included.
Contig
```
## Example
```tsx
import { GenomicRegionField } from "@noorddev/vlak-react";
```
## Props
### GenomicRegionField
A region in one-based inclusive coordinates. No assembly or half-open conversion is performed.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `reference` (required) | `string` | | Fixed reference name or accession, submitted with the region. |
| `contigs` (required) | `readonly GenomicContig[]` | | |
| `value` | `GenomicRegion` | | |
| `defaultValue` | `GenomicRegion` | `emptyRegion` | |
| `onValueChange` | `(value: GenomicRegion) => void` | | |
| `required` | `boolean` | `false` | |
| `readOnly` | `boolean` | `false` | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the contig, start and end controls. |
| Arrow keys, typing | Opens and navigates the Vlak contig selector or edits numeric inputs. Enter or Space confirms a contig; Escape closes its menu. |
## Accessibility
- A legend and visible labels name the group. Vlak Select and Input provide 44px controls; the coordinate convention is always visible.
- Validation rejects partial regions, non-integers, unsafe integers, positions below 1, reversed endpoints and coordinates beyond the supplied contig.
- Errors are linked to the controls and participate in native form validity. Invalid values remain editable without clamping.
- Missing reference metadata and invalid contig catalogs are explicit; zero never becomes position 1 automatically.
- Read-only fields preserve submitted values, disabled fieldsets do not submit, and controlled values remain application-owned.
## Classes
`rs-genomic-region-field`, `rs-genomic-region-field-legend`, `rs-genomic-region-field-fields`, `rs-genomic-region-field-label`, `rs-genomic-region-field-control`, `rs-genomic-region-field-copy`
## Dependencies
Registry dependencies: [input](input.md), [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/genomic-region-field.tsx`
CSS: `packages/core/css/components/genomic-region-field.css`
---
# Patchbay
Connects supplied source and destination ports through a keyboard-navigable matrix, with signal types, channel groups, and blocked-route reasons.
Category: creative
Name: `patchbay`
Also known as: Patchbay, Routing matrix, Audio routing, Crosspoint matrix, Connection matrix, Signal patching
Page: https://vlak.dev/components/patchbay/
## When to use
- An audio or signal-routing matrix whose ports and confirmed connections come from the host.
- value/defaultValue/onValueChange for controlled routing requests or a local prototype; the host applies real routing changes.
- Signal type strings must match; getBlockReason can add a host-specific restriction with a visible explanation.
- Existing incompatible connections can be disconnected; routes involving unavailable ports remain explicitly listed and preserved.
## When not to
- Assuming the component creates audio streams, manages clocking, or configures a routing engine.
- Silently deleting host connections when a port temporarily disappears.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Patchbay } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add patchbay
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/patchbay.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Source / destination
Monitor leftOutputs · audio
Mix leftMix bus · audio
```
## Example
```tsx
import { Patchbay } from "@noorddev/vlak-react";
```
## Props
### Patchbay
A connection matrix for supplied ports; the caller owns the routing engine.
Extends `Omit, "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `sources` (required) | `PatchPort[]` | | |
| `destinations` (required) | `PatchPort[]` | | |
| `value` | `PatchConnection[]` | | |
| `defaultValue` | `PatchConnection[]` | `[]` | |
| `onValueChange` | `(connections: PatchConnection[]) => void` | | |
| `getBlockReason` | `(source: PatchPort, destination: PatchPort) => string \| null` | | Additional host constraints. Matching signal types are required by default. |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Enters the connection matrix at one enabled checkbox, then leaves the matrix. |
| Arrow keys | Moves focus through enabled crosspoints in the same row or column. |
| Home, End | Moves to the first or last enabled crosspoint in the row; Control includes the whole matrix. |
| Space | Toggles the focused connection through the native checkbox. |
## Accessibility
- Native table headers identify sources and destinations; every checkbox also names both ports.
- Connection targets are at least 44px, with a full-surface checked state and forced-colors support.
- Blocked crosspoints expose reasons in text and descriptions. Roving focus skips disabled cells.
- Named checkboxes submit connection pairs; read-only hidden values preserve existing routes. Form reset restores uncontrolled defaults.
- The ref and native fieldset attributes reach the root fieldset.
## Classes
`rs-patchbay`, `rs-patchbay-legend`, `rs-patchbay-viewport`, `rs-patchbay-table`, `rs-patchbay-header`, `rs-patchbay-detail`, `rs-patchbay-cell`, `rs-patchbay-control`, `rs-patchbay-connected`, `rs-patchbay-blocked`, `rs-patchbay-input`, `rs-patchbay-note`
## Dependencies
Registry dependencies: none.
React: `packages/react/src/components/patchbay.tsx`
CSS: `packages/core/css/components/patchbay.css`
---
# Kerning pair editor
Edits supplied glyph-pair offsets in font units, with baseline and edited previews, bounded keyboard nudging, and one-step undo.
Category: creative
Name: `kerning-pair-editor`
Also known as: KerningPairEditor, Kerning editor, Glyph pair spacing, Font pair editor, Pair adjustment
Page: https://vlak.dev/components/kerning-pair-editor/
## When to use
- Supplied glyph strings, a caller-selected font family, and explicit units per em.
- value/defaultValue/onValueChange as a map from pair id to offset; null or an absent entry means not supplied.
- baselineOffsets to compare and reset a pair; missing baselines never imply zero.
- Optional min/max bounds default to negative and positive units per em; typed values retain native validation.
- activePairId/defaultActivePairId/onActivePairChange for caller-owned pair navigation.
## When not to
- Treating the preview as a font shaping engine, font-file editor, or source of baseline kerning.
- Assuming a requested font is installed; the browser uses its normal font fallback.
- Undoing external host changes; undo is available only while the latest requested edit remains current.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { KerningPairEditor } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add kerning-pair-editor
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/kerning-pair-editor.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Edited: -80 units
AV
```
## Example
```tsx
import { KerningPairEditor } from "@noorddev/vlak-react";
```
## Props
### KerningPairEditor
Explicit pair offsets with browser font previews, without font-file editing or shaping.
Extends `Omit, "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `pairs` (required) | `KerningPair[]` | | |
| `fontFamily` (required) | `string` | | |
| `unitsPerEm` (required) | `number` | | |
| `baselineOffsets` | `KerningOffsets` | `{}` | |
| `value` | `KerningOffsets` | | |
| `defaultValue` | `KerningOffsets` | `{}` | |
| `onValueChange` | `(offsets: KerningOffsets) => void` | | |
| `activePairId` | `string \| null` | | |
| `defaultActivePairId` | `string \| null` | | |
| `onActivePairChange` | `(id: string \| null) => void` | | |
| `min` | `number` | `-unitsPerEm` | |
| `max` | `number` | `unitsPerEm` | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the pair selector, navigation, offset editor, reset, and undo actions. |
| Arrow left, Arrow right | Nudges the focused offset by one font unit within the supplied bounds. |
| Shift + Arrow left, Shift + Arrow right | Nudges the focused offset by ten font units. |
| Enter, Space | Activates the focused previous, next, reset, or undo button. |
## Accessibility
- A fieldset and legend name the editor; Vlak Select and Input controls have 44px targets.
- Baseline and edited offsets remain text, and each pair preview has an accessible description.
- Preview spacing is offset divided by units per em; intrinsic browser kerning and ligatures are disabled for the comparison.
- Missing or invalid font units suppress geometry; typed out-of-bounds values expose native validity and a visible explanation.
- The ref and native attributes reach the fieldset. Named offsets submit per pair; reset restores uncontrolled offsets and clears undo.
## Classes
`rs-kerning-pair-editor`, `rs-kerning-pair-editor-legend`, `rs-kerning-pair-editor-toolbar`, `rs-kerning-pair-editor-field`, `rs-kerning-pair-editor-input`, `rs-kerning-pair-editor-button`, `rs-kerning-pair-editor-previews`, `rs-kerning-pair-editor-preview`, `rs-kerning-pair-editor-glyphs`, `rs-kerning-pair-editor-glyph`, `rs-kerning-pair-editor-note`
## Dependencies
Registry dependencies: [select](select.md), [input](input.md), [button](button.md).
React: `packages/react/src/components/kerning-pair-editor.tsx`
CSS: `packages/core/css/components/kerning-pair-editor.css`
---
# Assembly variant matrix
Edits independent population, bill-of-materials, and placement flags per reference and assembly variant, preserving unspecified choices.
Category: electronics
Name: `assembly-variant-matrix`
Also known as: AssemblyVariantMatrix, Assembly options, Population matrix, Bill of materials variants, Placement options, Reference variant table
Page: https://vlak.dev/components/assembly-variant-matrix/
## When to use
- Caller-owned assembly references, part labels, and named build variants.
- Three independent boolean-or-null flags: population, bill-of-materials inclusion, and placement-file inclusion.
- value/defaultValue/onValueChange to receive the proposed cell array; editing one flag leaves the other flags unchanged.
- Missing cells begin unspecified. Conflicting duplicate cells and unavailable references remain visible rather than being silently merged.
## When not to
- Inferring bill-of-materials or placement policy from the populated flag.
- Assuming the component generates manufacturing files or changes a board design.
- Treating unspecified flags as excluded or not populated.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { AssemblyVariantMatrix } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add assembly-variant-matrix
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/assembly-variant-matrix.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Reference / variant
Pilot
R110 kΩ resistor
Edit R1 in PilotNot specified
Populated
```
## Example
```tsx
import { AssemblyVariantMatrix } from "@noorddev/vlak-react";
```
## Props
### AssemblyVariantMatrix
Independent fitted, bill-of-materials and placement choices per reference and variant.
Extends `Omit, "defaultValue" | "onChange">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `references` (required) | `AssemblyReference[]` | | |
| `variants` (required) | `AssemblyVariant[]` | | |
| `value` | `AssemblyVariantState[]` | | |
| `defaultValue` | `AssemblyVariantState[]` | `[]` | |
| `onValueChange` | `(cells: AssemblyVariantState[]) => void` | | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through native cell summaries and controls in expanded editors. |
| Enter, Space | Opens or closes the focused cell's native details editor. |
| Arrow keys | Opens and navigates the Vlak selector between Unspecified, Yes, and No; Enter confirms the highlighted choice. |
## Accessibility
- Native row and column headers identify each reference and variant; cell editor summaries repeat that context.
- Each independent Vlak Select has a flag-specific name including its reference and variant, and a 44px target.
- Compact summaries expose all three flags in text; no color or population shortcut carries policy.
- Native details reveal the editor without focus traps; Vlak Select supplies the choice menu, and overflow remains inside the matrix.
- Named controls submit each flag separately. Read-only values and native form reset are supported; the ref reaches the fieldset.
## Classes
`rs-assembly-variant-matrix`, `rs-assembly-variant-matrix-legend`, `rs-assembly-variant-matrix-viewport`, `rs-assembly-variant-matrix-table`, `rs-assembly-variant-matrix-header`, `rs-assembly-variant-matrix-part`, `rs-assembly-variant-matrix-cell`, `rs-assembly-variant-matrix-details`, `rs-assembly-variant-matrix-summary`, `rs-assembly-variant-matrix-editor`, `rs-assembly-variant-matrix-field`, `rs-assembly-variant-matrix-select`, `rs-assembly-variant-matrix-note`
## Dependencies
Registry dependencies: [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/assembly-variant-matrix.tsx`
CSS: `packages/core/css/components/assembly-variant-matrix.css`
---
# Alarm panel
Industrial alarm records with independent condition, acknowledgement and shelving states, explicit filters and host-confirmed actions.
Category: engineering
Name: `alarm-panel`
Also known as: Industrial alarms, Alarm acknowledgement, Alarm shelving, Operator alarm list, Process alarm panel
Page: https://vlak.dev/components/alarm-panel/
## When to use
- Operator alarm lists with supplied lifecycle fields and explicit unknown values.
- Supply allowed actions and onAction to request acknowledgement, shelving or unshelving. Return pending and then confirmed records from the host.
- Use filter and onFilterChange for an application-owned filter; uncontrolled filtering starts from defaultFilter.
- Provide unique alarm ids, a bounded set of visible records, event time labels and the site's explicit time-zone context.
## When not to
- Treating acknowledgement as clearing a condition, or shelving as acknowledgement.
- Using a displayed action as proof that equipment changed state. The host owns permissions, audit records, filtering of large streams and shelving timers.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { AlarmPanel } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add alarm-panel
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/alarm-panel.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Plant alarms
Cooling flow
Condition
Cleared
Acknowledgement
Unacknowledged
Shelving
Not shelved
```
## Example
```tsx
import { AlarmPanel } from "@noorddev/vlak-react";
```
## Props
### AlarmPanel
An industrial alarm's condition, acknowledgement and shelving are independent records.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `alarms` (required) | `readonly AlarmRecord[]` | | |
| `filter` | `AlarmFilter` | | |
| `defaultFilter` | `AlarmFilter` | `"all"` | |
| `onFilterChange` | `(filter: AlarmFilter) => void` | | |
| `onAction` | `(id: string, action: AlarmAction) => void` | | Requests an operation. Update the supplied record only after the host confirms it. |
| `disabled` | `boolean` | | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through filter buttons and supplied enabled alarm actions. |
| Enter, Space | Applies a filter or requests the focused action. |
## Accessibility
- Each alarm exposes separate condition, acknowledgement and shelving fields as visible text in a description list.
- Pressed filter buttons use a full fill; all controls have 44px targets, visible keyboard focus and forced-colour support.
- A polite record count reflects the current filter. Pending records keep their confirmed state and disable actions.
- The div ref, native attributes, className and style pass through.
## Classes
`rs-alarm-panel`, `rs-alarm-panel-heading`, `rs-alarm-panel-copy`, `rs-alarm-panel-filters`, `rs-alarm-panel-button`, `rs-alarm-panel-selected`, `rs-alarm-panel-list`, `rs-alarm-panel-item`, `rs-alarm-panel-head`, `rs-alarm-panel-states`, `rs-alarm-panel-term`, `rs-alarm-panel-value`, `rs-alarm-panel-actions`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/alarm-panel.tsx`
CSS: `packages/core/css/components/alarm-panel.css`
---
# Work offset panel
Reported machine and work coordinates alongside editable draft offsets, explicit axis units and a host-owned apply request.
Category: engineering
Name: `work-offset-panel`
Also known as: Machine coordinates, Work coordinate system, Fixture offsets, Machining offsets, Coordinate readout
Page: https://vlak.dev/components/work-offset-panel/
## When to use
- Editing a supplied offset record while keeping actual machine and work readings visible.
- Supply both reported coordinate sets independently; rotations and additional offsets belong to the controller, so no machine-to-work subtraction is inferred.
- value and onValueChange let the host load offsets for a chosen draft system. Uncontrolled system changes retain the entered offsets; they do not fetch another system's record.
- onApply requests a complete finite draft containing only the listed axes and a known enabled system. activeSystemId, offsetState and actual readings change only when supplied by the host.
- name submits name.system and name.axisId values. External form association and native reset are supported.
## When not to
- Interpreting an apply request as controller acceptance, machine movement or persistence.
- Treating missing coordinates as zero, or suspended offsets as zeroed offsets. The host owns controller access, validation and interlocks.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { WorkOffsetPanel } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add work-offset-panel
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/work-offset-panel.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Active system: G54 · Offsets active
Draft coordinate system
```
## Example
```tsx
import { WorkOffsetPanel } from "@noorddev/vlak-react";
```
## Props
### WorkOffsetPanel
Edit a proposed offset while retaining independently supplied machine and work positions.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `axes` (required) | `readonly WorkOffsetAxis[]` | | |
| `systems` (required) | `readonly WorkOffsetSystem[]` | | |
| `activeSystemId` (required) | `string \| null` | | Actual active system reported by the controller, independent of the draft selection. |
| `value` | `WorkOffsetValue` | | |
| `defaultValue` | `WorkOffsetValue` | `{ systemId: null, offsets: {} }` | |
| `onValueChange` | `(value: WorkOffsetValue) => void` | | |
| `onApply` | `(value: WorkOffsetValue) => void` | | Request a complete offset update; machine control and coordinate calculations belong to the host. |
| `offsetState` | `"active" \| "suspended" \| "unknown"` | `"unknown"` | |
| `pending` | `boolean` | `false` | |
| `readOnly` | `boolean` | `false` | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the system selector, scroll region, axis offset inputs and apply action. |
| Arrow keys | Opens and navigates the Vlak system selector, steps number inputs or scrolls the focused table region. Escape closes the selector. |
| Enter, Space | Confirms a highlighted system or requests the focused Apply offsets action when a complete draft is available. |
## Accessibility
- A fieldset and legend name the editor. A captioned table separates actual readings from draft values, with axis units in each accessible input name.
- Unknown, unavailable and zero readings remain distinct. Invalid supplied offsets are marked and prevent apply.
- Vlak Select, Input and Button retain 44px targets; narrow layouts scroll the table inside a focusable, uniquely named region.
- Read-only values remain submittable; disabled or pending controls do not submit. Native reset restores uncontrolled defaults without overwriting controlled values.
- The fieldset ref, native attributes, className and style pass through.
## Classes
`rs-work-offset-panel`, `rs-work-offset-panel-legend`, `rs-work-offset-panel-copy`, `rs-work-offset-panel-field`, `rs-work-offset-panel-control`, `rs-work-offset-panel-viewport`, `rs-work-offset-panel-table`, `rs-work-offset-panel-caption`, `rs-work-offset-panel-cell`, `rs-work-offset-panel-axis`, `rs-work-offset-panel-offset`, `rs-work-offset-panel-button`
## Dependencies
Registry dependencies: [input](input.md), [select](select.md), [button](button.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/work-offset-panel.tsx`
CSS: `packages/core/css/components/work-offset-panel.css`
---
# Joint panel
Pairs host-reported joint positions with independent draft targets, supplied units and limits, and an explicit request action.
Category: robotics
Name: `joint-panel`
Also known as: JointPanel, Robot joint targets, Joint monitor, Joint position editor, Robot axis targets
Page: https://vlak.dev/components/joint-panel/
## When to use
- Reported joint positions and a separate draft target map keyed by joint identifier.
- value/defaultValue/onValueChange for controlled editing or an isolated prototype; drafts never inherit missing values from reported positions.
- Finite minimum and maximum values in each joint's supplied unit. A complete valid draft is required before requesting targets.
- onRequestTargets to ask the host to apply a draft; pending and confirmedLabel describe independently supplied request state.
- Missing, non-finite, duplicate, and unlisted records receive explicit feedback. No motion or limit policy is inferred.
## When not to
- Treating a successful click as confirmed robot movement.
- Using the component as a motion planner, interlock, unit converter, or source of joint limits.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { JointPanel } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add joint-panel
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/joint-panel.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Reported at: 12:00:00.125
Shoulder
Reported: 12.5 deg
Limits: -90 to 90 deg
```
## Example
```tsx
import { JointPanel } from "@noorddev/vlak-react";
console.log("Requested targets", targets)} />
```
## Props
### JointPanel
Draft joint targets remain separate from host-reported positions and request confirmation.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `joints` (required) | `readonly JointRecord[]` | | |
| `value` | `JointTargets` | | |
| `defaultValue` | `JointTargets` | `{}` | |
| `onValueChange` | `(targets: JointTargets) => void` | | |
| `onRequestTargets` | `(targets: JointTargets) => void` | | Requests the complete draft. Motion and confirmation belong to the host. |
| `pending` | `boolean` | `false` | |
| `confirmedLabel` | `ReactNode` | | |
| `timeLabel` | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through target inputs and the request button. |
| Arrow up, Arrow down | Uses native number-input stepping within the supplied limits. |
| Enter, Space | Activates the focused request button when the complete draft is valid. |
## Accessibility
- The fieldset and legend name the joint group; each target names its joint and unit.
- Vlak Input and Button provide consistent control sizing, focus treatment, and native keyboard behavior.
- Native validity and visible messages identify missing or out-of-bounds targets; reported zero remains distinct from missing data.
- Named inputs submit per-joint drafts. Form reset restores uncontrolled defaults, read-only drafts still submit, and pending controls are disabled.
- The ref, native fieldset attributes, className, and style reach the root fieldset.
## Classes
`rs-joint-panel`, `rs-joint-panel-legend`, `rs-joint-panel-copy`, `rs-joint-panel-list`, `rs-joint-panel-joint`, `rs-joint-panel-title`, `rs-joint-panel-reading`, `rs-joint-panel-field`, `rs-joint-panel-input`, `rs-joint-panel-button`
## Dependencies
Registry dependencies: [input](input.md), [button](button.md).
React: `packages/react/src/components/joint-panel.tsx`
CSS: `packages/core/css/components/joint-panel.css`
---
# Robot pose
Displays exact Cartesian translation and explicitly named orientation components for a selected supplied pose, with frame, time, and recorded status.
Category: robotics
Name: `robot-pose`
Also known as: RobotPose, Pose inspector, Cartesian pose, Robot pose record, Quaternion inspector, End effector pose
Page: https://vlak.dev/components/robot-pose/
## When to use
- Caller-supplied pose records with a frame, time label, recorded status, translation unit, and explicit orientation representation.
- value/defaultValue/onValueChange to select a supplied record by identifier; changing records does not transform coordinates.
- orientation.components for exact named values, with optional per-component units. Include axis order and intrinsic or extrinsic conventions in the representation label when relevant.
- Missing values remain Not supplied, non-finite values remain Unavailable, and zero is never treated as missing.
- The first supplied record is selected by default; an explicit null leaves the selection empty.
## When not to
- Treating the view as a frame tree, transform calculator, quaternion normalizer, or inverse-kinematics solver.
- Omitting orientation conventions or presenting an unconfirmed pose as the robot's active target.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { RobotPose } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add robot-pose
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/robot-pose.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Frame
base
Recorded at
12:00:00.125
Translation
Unit: m
X
0.125
Y
0
Z
0.25
Representation: Quaternion, x y z w
```
## Example
```tsx
import { RobotPose } from "@noorddev/vlak-react";
```
## Props
### RobotPose
Exact supplied Cartesian and orientation records, with no frame transform or pose computation.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `poses` (required) | `readonly RobotPoseRecord[]` | | |
| `value` | `string \| null` | | |
| `defaultValue` | `string \| null` | | |
| `onValueChange` | `(poseId: string \| null) => void` | | |
| `readOnly` | `boolean` | `false` | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the Vlak pose-record selector. |
| Enter, Space, Arrow keys | Opens and navigates the selector; Enter confirms the highlighted record. |
| Home, End, Escape | Moves to an end of the menu or closes it without changing the record. |
## Accessibility
- A fieldset and legend name the pose view; the Vlak Select names the recorded-pose choice and its menu.
- Definition lists retain every translation and orientation component as exact text, including zero, missing values, and explicit units.
- A named selection submits its supplied pose identifier through a hidden input. Parent form reset restores uncontrolled selection.
- Read-only selection retains its submitted value; native disabled fieldsets omit it.
- The ref and native attributes reach the root fieldset. No live announcement is attached to streamed pose data.
## Classes
`rs-robot-pose`, `rs-robot-pose-legend`, `rs-robot-pose-field`, `rs-robot-pose-select`, `rs-robot-pose-metadata`, `rs-robot-pose-detail`, `rs-robot-pose-heading`, `rs-robot-pose-values`, `rs-robot-pose-value`, `rs-robot-pose-text`, `rs-robot-pose-copy`
## Dependencies
Registry dependencies: [select](select.md).
React: `packages/react/src/components/robot-pose.tsx`
CSS: `packages/core/css/components/robot-pose.css`
---
# Robot mission queue
Shows supplied mission order and recorded step states, with keyboard reorder requests and explicit host actions separate from pending and confirmed records.
Category: robotics
Name: `robot-mission-queue`
Also known as: RobotMissionQueue, Robot task queue, Mission plan, Robot job sequence, Mission steps
Page: https://vlak.dev/components/robot-mission-queue/
## When to use
- A caller-owned ordered step list, explicit recorded statuses, and only those actions the host makes available.
- onOrderChange receives step identifiers in the proposed order. The host supplies the resulting records; the queue never rewrites status on a reorder request.
- onAction receives a step identifier and supplied action identifier. pending and confirmedLabel remain separate host records.
- Pending steps lock their own actions and adjacent reorder controls. readOnly keeps all request controls disabled.
- Named hidden inputs submit the supplied step identifiers in order; invalid duplicate step or action identifiers suppress ambiguous controls.
## When not to
- Assuming a request starts, cancels, schedules, or confirms physical execution.
- Using display order as an execution dependency graph or deriving allowed actions from a status string.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { RobotMissionQueue } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add robot-mission-queue
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/robot-mission-queue.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Inspect station
Recorded: Not started
Reordering and actions request host changes. Reported mission state remains supplied by the host.
```
## Example
```tsx
import { RobotMissionQueue } from "@noorddev/vlak-react";
console.log("Requested order", ids)}
onAction={(stepId, actionId) => console.log("Requested action", stepId, actionId)} />
```
## Props
### RobotMissionQueue
A supplied mission order, recorded step states, and explicit host request actions.
Extends `FieldsetHTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `steps` (required) | `readonly RobotMissionStep[]` | | |
| `onOrderChange` | `(stepIds: readonly string[]) => void` | | Proposed step identifiers in order; the host confirms and supplies the resulting records. |
| `onAction` | `(stepId: string, actionId: string) => void` | | |
| `readOnly` | `boolean` | `false` | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through enabled reorder and host-action buttons. |
| Enter, Space | Requests the focused reorder or supplied host action. |
## Accessibility
- The fieldset and legend name the mission, and a native ordered list conveys its supplied order.
- Vlak Button actions name both the step number and label. Reorder buttons state their direction and disable at list boundaries.
- Recorded status, host confirmation, and request-pending text remain distinct; pending feedback uses a status role.
- Action descriptions are connected to the corresponding button, including its recorded status.
- The ref and native fieldset attributes reach the root, and read-only ordered records remain available to forms.
## Classes
`rs-robot-mission-queue`, `rs-robot-mission-queue-legend`, `rs-robot-mission-queue-list`, `rs-robot-mission-queue-step`, `rs-robot-mission-queue-head`, `rs-robot-mission-queue-title`, `rs-robot-mission-queue-copy`, `rs-robot-mission-queue-status`, `rs-robot-mission-queue-actions`, `rs-robot-mission-queue-button`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/robot-mission-queue.tsx`
CSS: `packages/core/css/components/robot-mission-queue.css`
---
# Pad inspector
Circuit-board pad selection with supplied footprint references, net and layer records, pad types and a dimension table with explicit units.
Category: electronics
Name: `pad-inspector`
Also known as: Footprint pad, Circuit board pad properties, Pad geometry, Copper pad inspector, Board pad selector
Page: https://vlak.dev/components/pad-inspector/
## When to use
- Inspecting a bounded collection of pad records supplied by a board editor or manufacturing export.
- Supply unique, non-empty pad ids and unique measurement ids within each pad. Pad numbers may repeat; ids identify the actual records.
- Use value and onValueChange for host-owned selection and board or schematic cross-highlighting. No connectivity or geometry calculation runs in the component.
- Supply geometry values as strings to preserve significant figures. Null fields remain explicitly missing; an empty layers array means none recorded.
## When not to
- Inferring that a missing net means unconnected, a missing drill means no hole, or an unknown layer list means every copper layer.
- Treating selection as a board edit or inferring dimensions from the shape name.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { PadInspector } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add pad-inspector
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/pad-inspector.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Pad
Net
Supply
Layers
Front copper, Back copper
Supplied geometry
Dimension
Value
Unit
Pad diameter
1.80
mm
```
## Example
```tsx
import { PadInspector } from "@noorddev/vlak-react";
```
## Props
### PadInspector
Inspects supplied pad records without inferring connectivity, shape or dimensions.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `pads` (required) | `readonly PadInspectorPad[]` | | |
| `value` | `string \| null` | | |
| `defaultValue` | `string \| null` | `null` | |
| `onValueChange` | `(id: string \| null) => void` | | Requests pad selection only. The host owns board and schematic cross-highlighting. |
| `boardLabel` | `ReactNode` | | |
| `description` | `ReactNode` | | |
| `selectionLabel` | `string` | `"Pad"` | |
| `required` | `boolean` | | |
| `readOnly` | `boolean` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Focuses the Vlak pad selector. |
| Arrow keys, Home, End | Opens or moves through available pad choices. |
| Enter, Space | Chooses the focused pad. Controlled selection waits for a host update. |
| Escape | Closes the selector and keeps the current choice. |
## Accessibility
- A fieldset legend names the inspector. Pad choices include their record id, so repeated pad numbers remain distinguishable.
- Vlak Select supplies the 44px trigger, keyboard listbox and disabled choices. Pad properties use a description list and dimensions use a captioned table with row and column headers.
- Missing records, unavailable selections, non-finite measurements and missing units have explicit text. Numeric zero and string precision are retained.
- Native form association and reset are supported. Read-only valid selection remains submittable, while disabled selection is omitted.
- The fieldset ref, native attributes, className and style pass through.
## Classes
`rs-pad-inspector`, `rs-pad-inspector-legend`, `rs-pad-inspector-label`, `rs-pad-inspector-control`, `rs-pad-inspector-properties`, `rs-pad-inspector-term`, `rs-pad-inspector-detail`, `rs-pad-inspector-table`, `rs-pad-inspector-caption`, `rs-pad-inspector-cell`, `rs-pad-inspector-note`
## Dependencies
Registry dependencies: [select](select.md), [dropdown-menu](dropdown-menu.md).
React: `packages/react/src/components/pad-inspector.tsx`
CSS: `packages/core/css/components/pad-inspector.css`
---
# Design rule results
Supplied board-check violations with severity and status filters, object and location details, and host-confirmed selection and resolution actions.
Category: electronics
Name: `design-rule-results`
Also known as: Board rule check, Circuit board violations, Clearance results, Design-rule review, Board verification results
Page: https://vlak.dev/components/design-rule-results/
## When to use
- Reviewing a bounded set of results supplied by a board design-rule checker.
- Supply unique result ids, the confirmed severity and status, and any available layer, net, object and location records. Null severity or status means unknown.
- onSelect requests host selection; selectedId confirms it. onResolve requests resolution of an open result unless canResolve is false. Pending and disabled records cannot invoke actions.
- Use filter and onFilterChange for host-owned filters; uncontrolled filters start from defaultFilter. Named filters submit as name.severity and name.status.
## When not to
- Treating an action click as a resolved board defect or treating an excluded result as resolved.
- Inferring that an empty result array means a check ran or passed. The component does not run rules, edit the board or invent clearance limits.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { DesignRuleResults } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add design-rule-results
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/design-rule-results.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Synthetic check run 042
Copper clearance
Severity
Error
Confirmed status
Open
Layer
Front copper
Location
X: 24.5, Y: 18; unit: mm
```
## Example
```tsx
import { DesignRuleResults } from "@noorddev/vlak-react";
```
## Props
### DesignRuleResults
Supplied rule-check outcomes with local or controlled filters and host-confirmed actions.
Extends `Omit, "onSelect">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLFieldSetElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` | | |
| `violations` (required) | `readonly DesignRuleViolation[]` | | |
| `filter` | `DesignRuleFilter` | | |
| `defaultFilter` | `DesignRuleFilter` | `initial` | |
| `onFilterChange` | `(filter: DesignRuleFilter) => void` | | |
| `selectedId` | `string \| null` | | |
| `onSelect` | `(id: string) => void` | | Requests selection in the host board viewer; selectedId remains host-owned. |
| `onResolve` | `(id: string) => void` | | Requests resolution of an open result. Confirmed status never changes locally. |
| `runLabel` | `ReactNode` | | |
| `description` | `ReactNode` | | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through the Vlak filter selectors and available action buttons. |
| Arrow keys, Home, End | Navigates a focused filter's choices. |
| Enter, Space | Chooses a filter or requests the focused selection or resolution action. |
| Escape | Closes an open filter selector. |
## Accessibility
- A fieldset legend names the results. Vlak Select and Button provide shared control paint, focus states and 44px targets.
- Visible description lists distinguish reported severity, confirmed status, layer, net and coordinate units. Action names include the unique result id and title.
- The polite count distinguishes filtered results from the complete supplied set. Empty results and unmatched filters use different messages.
- Selected records use a full-surface fill and Selected text. Pending actions keep confirmed data readable and disable the action controls.
- Native form reset restores uncontrolled filters; controlled filters remain with the application. Disabled fieldsets omit filter values and block actions.
- The fieldset ref, native attributes, className and style pass through.
## Classes
`rs-design-rule-results`, `rs-design-rule-results-legend`, `rs-design-rule-results-filters`, `rs-design-rule-results-label`, `rs-design-rule-results-control`, `rs-design-rule-results-list`, `rs-design-rule-results-item`, `rs-design-rule-results-selected`, `rs-design-rule-results-title`, `rs-design-rule-results-properties`, `rs-design-rule-results-term`, `rs-design-rule-results-detail`, `rs-design-rule-results-actions`, `rs-design-rule-results-action`, `rs-design-rule-results-note`
## Dependencies
Registry dependencies: [select](select.md), [button](button.md).
React: `packages/react/src/components/design-rule-results.tsx`
CSS: `packages/core/css/components/design-rule-results.css`
---
# Colony plate
A bounded plate diagram and keyboard-selectable list of supplied colony markers, with the source count kept separate from annotation totals.
Category: microbiology
Name: `colony-plate`
Also known as: Colony annotations, Petri dish map, Colony record viewer, Agar plate annotations, Plate colony inspector
Page: https://vlak.dev/components/colony-plate/
## When to use
- Inspect supplied colony annotations and source counts without running an image analysis algorithm.
- recordedCount is the original source count. The exact number of supplied marker records and positioned records are labelled separately; neither substitutes for the source count.
- Supply unique marker identifiers and normalized x/y percentages from the upper left. The circular plate has center 50, 50 and radius 50.
- Select a record using value and onValueChange, or use defaultValue for local selection. Native form reset restores uncontrolled selection. readOnly keeps the same record list without selection controls.
## When not to
- Inferring a colony count from marker records, missing annotations or a blank diagram.
- Identifying organisms, segmenting images or suggesting culture procedures from these records.
- Supplying more than 256 markers; the component reports the bound without showing a partial list.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { ColonyPlate } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add colony-plate
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/colony-plate.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Colony annotations
Source count: 12
1 marker records supplied; 1 positioned
1. Colony 01
x 28%, y 32%
```
## Example
```tsx
import { ColonyPlate } from "@noorddev/vlak-react";
```
## Props
### ColonyPlate
A supplied plate record. Marker positions and source count are never detected or inferred.
Extends `Omit, "defaultValue">`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `markers` (required) | `readonly ColonyMarker[]` | | |
| `plateId` | `string` | | |
| `source` | `ReactNode` | | |
| `recordedCount` | `number \| null` | | The source's recorded count, independent of the number of supplied marker records. |
| `value` | `string \| null` | | |
| `defaultValue` | `string \| null` | `null` | |
| `onValueChange` | `(id: string \| null) => void` | | |
| `readOnly` | `boolean` | `false` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves through enabled record-selection buttons and the clear-selection button. |
| Enter, Space | Selects the focused supplied record or clears the selection; controlled selection waits for the host. |
## Accessibility
- The figure caption names the plate. The decorative diagram is paired with a complete ordered list of record labels, exact coordinates and supplied descriptions.
- Missing, non-finite and out-of-dish positions retain their list records and have explicit availability text. Only positioned markers are drawn; their exact number is shown.
- Every control is at least 44px with a visible focus ring. Selected record buttons use a full fill and aria-pressed, including in forced colors.
- Source count zero remains zero. Missing source counts and invalid negative or unsafe counts receive separate text; no count is inferred from the diagram.
- Duplicate or empty identifiers and oversized inputs produce an explanation. Native attributes, figure ref, className and style pass through. Selection buttons do not submit forms.
## Classes
`rs-colony-plate`, `rs-colony-plate-title`, `rs-colony-plate-copy`, `rs-colony-plate-count`, `rs-colony-plate-body`, `rs-colony-plate-graphic`, `rs-colony-plate-dish`, `rs-colony-plate-list`, `rs-colony-plate-record`, `rs-colony-plate-static`, `rs-colony-plate-details`, `rs-colony-plate-clear`, `rs-colony-plate-marker`, `rs-colony-plate-chosen`, `rs-colony-plate-control`, `rs-colony-plate-selected`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/colony-plate.tsx`
CSS: `packages/core/css/components/colony-plate.css`
---
# Culture log
A culture and sample record with supplied medium, conditions, chronological observations and host-owned recording actions.
Category: microbiology
Name: `culture-log`
Also known as: Culture notebook, Culture observations, Microbiology log, Culture record, Sample culture history
Page: https://vlak.dev/components/culture-log/
## When to use
- Review culture identity, sample identity, medium and conditions as supplied by the host.
- Provide offset-bearing timestamps for chronological ordering. Equal timestamps retain their supplied order; missing and invalid timestamps sort after dated observations.
- Supply actions and onAction to request recording changes. Update status or observations only when the host has accepted the change; pending disables actions without changing recorded state.
- Use oldest or newest ordering for at most 256 observations, 32 conditions and 16 actions with unique non-empty identifiers.
## When not to
- Inferring organism identity, contamination, growth interpretation or culture success from a status or observation.
- Generating a culture recipe, an incubation recommendation or a procedure from the displayed conditions.
- Treating a requested recording action as confirmation that a laboratory procedure occurred.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { CultureLog } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add culture-log
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/culture-log.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
Culture observations
Awaiting record review
Culture
C-042
Sample
S-042
Medium
Agar medium A
Sample record received
```
## Example
```tsx
import { useState } from "react";
import { CultureLog } from "@noorddev/vlak-react";
function CultureRecord() {
const [reviewed, setReviewed] = useState(false);
return setReviewed(true)} />;
}
```
## Props
### CultureLog
A chronological notebook of supplied culture observations, without protocol recommendations.
Extends `HTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLDivElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | | |
| `cultureId` (required) | `string` | | |
| `sampleId` (required) | `string` | | |
| `observations` (required) | `readonly CultureObservation[]` | | |
| `medium` | `ReactNode` | | |
| `status` | `string \| null` | | |
| `conditions` | `readonly CultureCondition[]` | `[]` | |
| `actions` | `readonly CultureAction[]` | `[]` | |
| `onAction` | `(actionId: string) => void` | | Requests a host recording action without changing any supplied observation or status. |
| `pending` | `boolean` | `false` | |
| `order` | `"newest" \| "oldest"` | `"oldest"` | |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves between supplied links and enabled recording actions. |
| Enter, Space | Requests the focused action through onAction without submitting a surrounding form. |
## Accessibility
- A named group contains a description list for metadata and an ordered list of observations. Every valid dated observation has a native time element.
- Missing times and malformed dates remain explicitly undated. Dates without an offset and impossible calendar dates are not silently reinterpreted.
- Zero-valued conditions remain visible; empty values and non-finite numeric conditions have explicit availability labels. Supplied statuses remain unchanged during pending requests.
- Recording actions have 44px targets and visible focus rings. Their names include the culture identity and their descriptions reference the supplied status.
- Oversized or ambiguous record collections have a visible explanation instead of a partial timeline. The div ref, native attributes, className and style pass through.
## Classes
`rs-culture-log`, `rs-culture-log-head`, `rs-culture-log-title`, `rs-culture-log-copy`, `rs-culture-log-metadata`, `rs-culture-log-value`, `rs-culture-log-list`, `rs-culture-log-observation`, `rs-culture-log-time`, `rs-culture-log-content`, `rs-culture-log-observation-label`, `rs-culture-log-notes`, `rs-culture-log-actions`, `rs-culture-log-action`
## Dependencies
Registry dependencies: [button](button.md).
React: `packages/react/src/components/culture-log.tsx`
CSS: `packages/core/css/components/culture-log.css`
---
# Button
Triggers an action. Solid primary or 1px ghost, with a minimum 44px target at every size.
Category: actions
Name: `button`
Also known as: Button, Primary button, Ghost button, Secondary button
Page: https://vlak.dev/components/button/
## When to use
- One primary action per view, with ghost for the secondary action.
- Submitting a form or answering a dialog.
## When not to
- Navigation that changes the URL; use Link or a nav component.
- On and off state; use Toggle or Switch, which carry aria-pressed and aria-checked.
## Install
**React package.** Precompiled; no compiler to configure.
```sh
npm install @noorddev/vlak-react
```
```tsx
import "@noorddev/vlak-react/css";
import { Button } from "@noorddev/vlak-react";
```
**Vendor the source.** The StyleX leaf lands in `components/vlak/` for your compiler to own.
```sh
npx @noorddev/vlak-cli add button
```
**shadcn registry.** Same files, through the shadcn CLI.
```sh
npx shadcn add https://vlak.dev/r/button.json
```
**CSS only.** `rs-*` classes on plain markup, styled by `@noorddev/vlak/css`.
```html
```
## Example
```tsx
import { Button } from "@noorddev/vlak-react";
```
## Props
### Button
Extends `ButtonHTMLAttributes`: every native attribute, `className`, `style`, and event handler passes through.
Forwards `ref` to the `HTMLButtonElement`.
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"primary" \| "ghost"` | `"primary"` | Solid ink primary or hairline ghost. One primary per view. |
| `size` | `"default" \| "sm"` | `"default"` | |
| `grouped` | `boolean` | `false` | Flush into a ButtonGroup: no own stroke, one ink seam. |
## Keyboard
| Keys | Does |
| --- | --- |
| Tab | Moves focus to the button |
| Enter, Space | Activates it |
## Accessibility
- Renders a native