# Strata component anatomy

One page per component, with the headings from
[section 17 of the design language](https://underglass.dev/docs/strata/design-language#17-component-anatomy-template). Each page is
the component's **markup contract** (section 18): plain HTML, React, Vue and Astro render exactly the DOM
it shows, and binding tests compare against it.

## Conventions

**Class names** use the `ug-` prefix, Bootstrap-style: a block (`ug-button`), modifiers
(`ug-button--accent`) and parts (`ug-switch__knob`). States come from native pseudo-classes and ARIA or
native attributes (`:hover`, `:active`, `:focus-visible`, `:checked`, `:disabled`, `aria-invalid`,
`aria-busy`, `aria-pressed`), never from state classes.

**Strata attributes** use the `data-strata-` prefix:

| Attribute | On | Meaning |
| --- | --- | --- |
| `data-strata-face` | Any element the material pass lights | The relief primitive: `raised`, `well`, `groove`, `knob`, `mark`, `ring` or `flat` (below) |
| `data-strata-material` | A face, a component or a scope | A material role (`buttonPrimary`) or preset (`lacquer`); overrides the role default |
| `data-strata-elevation` | A raised face | An elevation token name (`raised`, `floating`); the component's default when absent |
| `data-strata-level` | A component or a scope | `relief`, `objects`, `instrument` or `scene`, overriding the scope's level |
| `data-strata-depth` | A scope | Depth for the subtree, 0–1 |
| `data-strata-theme` | The root or a scope | `light`, `dark`, `contrast` or `contrast-dark`; the root follows the system without it |
| `data-strata-density` | The root or a scope | `compact`, `comfortable` or `spacious` |
| `data-strata-size` | A component or a scope | `small`, `medium` (default) or `large`: indicator, switch and control sizes |
| `data-strata-mode` | The root or a scope | `face`: the GPU paints relief, so CSS paints flat faces (no bevel, shadow or finish) |
| `data-strata-preview` | A control | `hover`, `active` or `focus`: shows a state statically, for specimens and tests only |
| `data-strata-form` | A Switch's row, or a Button or ToggleButton | `slide`, `rocker`, `bat` or `wall`: the switch's hardware form ([Switch, Forms](https://underglass.dev/docs/strata/components/switch#11-forms)); `momentary` (Button) or `latching` (ToggleButton): a push button ([Button](https://underglass.dev/docs/strata/components/button#11-push-button-form-momentary), [ToggleButton](https://underglass.dev/docs/strata/components/toggle-button#11-push-button-form-latching)) |
| `data-strata-down` | A push button, or a latching form's key (`.ug-latch`) | `true` while it is held (the pointer or a key down), `false` once released: its ring lit and its cap down; set by `attachStrataPushButtons` |
| `data-strata-form` (latching forms) | A Checkbox's row, a RadioGroup's or SegmentedControl's fieldset | `latching` (Checkbox, SegmentedControl) or `bank` (RadioGroup): the native control drawn as latching buttons; `flush`, or none, is the look before ([Checkbox](https://underglass.dev/docs/strata/components/checkbox#11-latching-form-latching), [RadioGroup](https://underglass.dev/docs/strata/components/radio#11-hardware-forms-the-preset-bank-bank-and-the-rotary-selector-selector), [SegmentedControl](https://underglass.dev/docs/strata/components/segmented-control#11-latching-form-latching)) |
| `data-strata-form` (structural forms) | A Slider's drawn root (`.ug-knob`, `.ug-fader`), a Card, a Panel, a Dialog or a Drawer | `knob` or `fader` (Slider), `plate` or `tray` (Card, Panel), `plate` (Dialog) or `tray` (Drawer): the control drawn as the Knob's or the Fader's object over the Slider's own input, as a machined plate or a recessed tray, a plate that rises out of the chassis or a tray that slides out of its edge; `flush`, or none, is the look before ([Slider](https://underglass.dev/docs/strata/components/slider#11-hardware-forms-knob-fader-and-wheel), [Card](https://underglass.dev/docs/strata/components/card#11-plate-and-tray-forms), [Panel](https://underglass.dev/docs/strata/components/panel#11-plate-and-tray-forms), [Dialog](https://underglass.dev/docs/strata/components/dialog#11-plate-form), [Drawer](https://underglass.dev/docs/strata/components/drawer#11-tray-form)) |
| `data-strata-form` (select and tabs forms) | A Select's drawn root (`.ug-rotary`, `.ug-select-display` and its `.ug-display`), a Tabs' root | `selector` or `display` (Select: the RotarySelector's dial over the Select's own select, or a Display with two step buttons; a selector of more than eight options, long labels or optgroups is drawn as `display`), `rail` (Tabs: the tablist a plinth, each tab a latching key with an LED), `wheel` (Slider: the Fader's track with a ridged roller), `selector` (RadioGroup: the RotarySelector's dial over the radios; nine radios or a long label is drawn as `bank`); `flush`, or none, is the look before ([Select](https://underglass.dev/docs/strata/components/select#11-hardware-forms-selector-and-display), [Tabs](https://underglass.dev/docs/strata/components/tabs#11-rail-form-rail)) |
| `data-strata-segments` | A Display's root | `seven`: the text under the glass in the seven-segment face, with the unlit segments printed behind it; none is the display of before ([Display, section 11](https://underglass.dev/docs/strata/components/display#11-the-segments-look-a-seven-segment-face)) |
| `data-strata-step` | A display Select's step button | `-1` (previous) or `1` (next): the `selectedIndex` step a click makes ([Select](https://underglass.dev/docs/strata/components/select#11-hardware-forms-selector-and-display)) |
| `data-strata-colour` | A Lamp or StatusLight | The lens's colour role: `glowOn` (default), `accent`, `success`, `warning`, `danger` or `info` ([Lamp](https://underglass.dev/docs/strata/components/lamp)) |
| `data-strata-lit` | A StatusLight | `false`: an unlit light (lit when absent) |
| `data-strata-form` (indicator forms) | A Rating's fieldset, a Badge, a ProgressBar's wrapper (`.ug-progress-bar`) or a Spinner | `lamps` (Rating), `led` (Badge), `meter` (ProgressBar) or `ring` (Spinner): the control drawn as LED lenses, each an emitter lit by `--strata-lit`; `flush`, or none, is the look before. `data-strata-colour` is the lenses' role there too, `accent` by default for a bar and a ring ([Rating](https://underglass.dev/docs/strata/components/rating#11-indicator-form-lamps), [Badge](https://underglass.dev/docs/strata/components/badge#11-indicator-form-led), [ProgressBar](https://underglass.dev/docs/strata/components/progress-bar#11-indicator-form-meter), [Spinner](https://underglass.dev/docs/strata/components/spinner#11-indicator-form-ring)) |
| `data-strata-blink` | A StatusLight | A tempo token, `slow`, `normal` or `fast`: a lit light blinks, off under reduced motion ([StatusLight](https://underglass.dev/docs/strata/components/status-light)) |
| `data-strata-wrap` | A JogWheel's input | `"true"`: the value goes round at the ends, as the wheel does ([JogWheel](https://underglass.dev/docs/strata/components/jog-wheel)) |
| `data-strata-drag` | A JogWheel | `vertical`: a vertical drag, a turn per `jog.dragPx`, instead of the circular one |
| `data-strata-backlight` | A Display's root (`data-strata-form="display"`, a TextField's `display` form or a read-only Display) | The backlight's role: `glowOn` (default, absent), `accent`, `success`, `warning`, `danger`, `info` or `off`; `data-strata-lit="false"` on it switches the light off ([Display](https://underglass.dev/docs/strata/components/display)) |
| `data-strata-colour` (pads) | A Pad | The glow's colour role, as a Lamp's ([Pad](https://underglass.dev/docs/strata/components/pad)) |
| `data-strata-velocity` | A Pad | The last press's velocity, 0–1 (position, pressure or key), set at each press by `attachStrataPads`; optional ([Pad](https://underglass.dev/docs/strata/components/pad#8-keyboard-and-screen-reader)) |
| `data-strata-shifted` | A Keypad's fieldset | `true`: each key's second legend is printed large and its first small ([Keypad](https://underglass.dev/docs/strata/components/keypad)) |

**Relief primitives.** Each is a rounded box (or a circle) taken from the element's border box and its
`border-radius`. The GPU reads them from the markers, and the CSS presentation styles the same elements.

| Primitive | Shape | Lighting | Shadow | Examples |
| --- | --- | --- | --- | --- |
| `raised` | Rounded box at an elevation | Bevel lit from the light, interior within `interior.max` | Cast, from height | Button key, card, panel |
| `well` | Rounded box sunk by `elevation.well` | Inverted bevel: the edge nearest the light is dark | Inner, from the rim | Field, switch track, checkbox box |
| `groove` | A thin well, at most 8 px high | As `well`, narrower bevel | Inner | Progress bar, slider rail, divider |
| `knob` | Circle (or pill) on a well | Spherical shading | Cast onto the well | Switch knob, slider thumb, radio dot |
| `mark` | A glyph or shape raised inside a well | Bevel on its outline | Small cast | Check mark, indeterminate bar |
| `ring` | Annulus, with an optional arc | As `groove`; the arc as the fill | Inner | Spinner |
| `flat` | Rounded box, no height | Material only, no bevel | None | Badge, divider in forced colours |

**Edges.** Wells, tracks and unchecked marks carry a 1 px `colour.edge` outline, so their shape meets 3:1
against the panel ([non-text contrast](https://underglass.dev/docs/strata/design-language#8-colour)). Knobs carry one when they do not
reach 3:1 against their track.

**Derived parts.** A slider's puck and a progress bar's fill have no element of their own: the GPU and the
CSS pseudo-elements (`::-webkit-slider-thumb`, `::-webkit-progress-value` and their equivalents) place them
from the native value.

Moving parts (`knob`, `mark`, a pressed key) never change the native element's box. Their travel lives in
the GPU pose and in CSS `transform`, inside the box (the [footprint rule](https://underglass.dev/docs/strata/design-language#6-objects)).

**Overlays.** Dialog and Drawer are top-level panels rendered into a container: the page body, or the Underglass
root, where `@underglass/ui/gpu` presents each as its own GPU panel over a GPU-faded scrim. They are never inside a layer
and are made modal by `showStrataDialog` (inert background, focus, Escape). Other floating parts (menus, popovers,
tooltips, select popups) still portal to the Underglass overlay host and are CSS-presented there; Tooltip and Popover
portal to `<body>` and float in the top layer. Tier A has no
overlays: the native `<select>` opens the browser's own list.

## Specimen

The [specimen page](https://github.com/RaananW/underglass/blob/main/examples/playground/ui-specimen.html) (`ui-specimen.html` in the playground) shows
every token, material, elevation and Tier A state from `@underglass/ui/css` in plain HTML and CSS. Its browser
test is the accessibility harness: axe in every theme and under forced colours, contrast on decoded pixels, the
light and depth, reduced motion, keyboard input and reflow.

## Tier A

| Component | Native element | Object |
| --- | --- | --- |
| [Button](https://underglass.dev/docs/strata/components/button) | `<button>` | Key; `form="momentary"`: a push button, a machined cap with a lit ring |
| [IconButton](https://underglass.dev/docs/strata/components/icon-button) | `<button>` with `aria-label` | Square key |
| [ToggleButton](https://underglass.dev/docs/strata/components/toggle-button) | `<button aria-pressed>` | Latching key; `form="latching"`: a push button that stays down, with an LED |
| [ButtonGroup](https://underglass.dev/docs/strata/components/button-group) | `<div role="group">` | Keys on one plinth |
| [Link](https://underglass.dev/docs/strata/components/link) | `<a href>` | None (flat text) |
| [Field](https://underglass.dev/docs/strata/components/field) | `<div>` with `<label>`, help and error | None (layout) |
| [TextField](https://underglass.dev/docs/strata/components/text-field) | `<input>`; `form="display"`: a glass window in a bezel ([Display](https://underglass.dev/docs/strata/components/display)) | Well with a bezel |
| [TextArea](https://underglass.dev/docs/strata/components/text-area) | `<textarea>` | Well with a bezel |
| [Checkbox](https://underglass.dev/docs/strata/components/checkbox) | `<input type="checkbox">` | Small well with a raised mark; `form="latching"`: a small latching square button whose ring lights when checked ([Latching form](https://underglass.dev/docs/strata/components/checkbox#11-latching-form-latching)) |
| [Radio and RadioGroup](https://underglass.dev/docs/strata/components/radio) | `<input type="radio">` in `<fieldset>` | Round well with a knob; `form="bank"`: a preset bank, interlocking latching keys on one plinth ([Latching form](https://underglass.dev/docs/strata/components/radio#11-hardware-forms-the-preset-bank-bank-and-the-rotary-selector-selector)); `form="selector"`: the RotarySelector's dial over the same radios ([Selector](https://underglass.dev/docs/strata/components/radio#the-rotary-selector-selector)) |
| [Switch](https://underglass.dev/docs/strata/components/switch) | `<input type="checkbox" role="switch">` | Track well with a knob; hardware [forms](https://underglass.dev/docs/strata/components/switch#11-forms): slide, rocker, bat and wall |
| [Select](https://underglass.dev/docs/strata/components/select) | `<select>` | Key with a chevron; `form="selector"`: the RotarySelector's dial over the same select, `"display"`: a Display window with step buttons ([Hardware forms](https://underglass.dev/docs/strata/components/select#11-hardware-forms-selector-and-display)) |
| [Slider](https://underglass.dev/docs/strata/components/slider) | `<input type="range">` | Rail groove with a puck; `form="knob"`, `"fader"` or `"wheel"`: the Knob's or the Fader's object, or a ridged roller rolling in a slot, over the same input ([Hardware forms](https://underglass.dev/docs/strata/components/slider#11-hardware-forms-knob-fader-and-wheel)) |
| [Card](https://underglass.dev/docs/strata/components/card) | `<article>` or `<section>` | Raised slab; `form="plate"`: a machined plate, `"tray"`: the body a recessed tray ([Plate and tray forms](https://underglass.dev/docs/strata/components/card#11-plate-and-tray-forms)) |
| [Panel](https://underglass.dev/docs/strata/components/panel) | `<section>` | Raised slab, the GPU layer unit; `form="plate"` or `"tray"` as the Card ([Plate and tray forms](https://underglass.dev/docs/strata/components/panel#11-plate-and-tray-forms)) |
| [Divider](https://underglass.dev/docs/strata/components/divider) | `<hr>` | Groove |
| [Badge](https://underglass.dev/docs/strata/components/badge) | `<span>` | Flat pill; `form="led"`: an LED pill, the StatusLight's lens before the text ([Indicator form](https://underglass.dev/docs/strata/components/badge#11-indicator-form-led)) |
| [Spinner](https://underglass.dev/docs/strata/components/spinner) | `<span role="status">` | Ring groove with an emissive arc; `form="ring"`: a ring of eight LEDs chasing at `chase.spinner` ([Indicator form](https://underglass.dev/docs/strata/components/spinner#11-indicator-form-ring)) |
| [ProgressBar](https://underglass.dev/docs/strata/components/progress-bar) | `<progress>` | Groove with an emissive fill; `form="meter"`: a groove of LED segments lit from the value, a running head while indeterminate ([Indicator form](https://underglass.dev/docs/strata/components/progress-bar#11-indicator-form-meter)) |

## Tier B

| Component | Native element | Object |
| --- | --- | --- |
| [Dialog](https://underglass.dev/docs/strata/components/dialog) | `<section role="dialog" aria-modal>` | Raised slab at `elevation.modal`, over a scrim; `form="plate"`: a plate that rises out of the chassis ([Plate form](https://underglass.dev/docs/strata/components/dialog#11-plate-form)) |
| [Drawer](https://underglass.dev/docs/strata/components/drawer) | `<section role="dialog" aria-modal>` | Raised slab on a viewport edge; `form="tray"`: a tray that slides out of its edge ([Tray form](https://underglass.dev/docs/strata/components/drawer#11-tray-form)) |
| [Accordion](https://underglass.dev/docs/strata/components/accordion) | `<details>` with `<summary>` | A stack of raised slabs; the header's chevron turns |
| [AppBar](https://underglass.dev/docs/strata/components/app-bar) | `<header>` | A raised slab across the top, with controls on it |
| [Avatar](https://underglass.dev/docs/strata/components/avatar) | `<span role="img">` or an `<img>` | A raised coin |
| [Chip and Tag](https://underglass.dev/docs/strata/components/chip) | `<span>`, or `<button aria-pressed>` | A small raised pill; a filter chip latches |
| [Breadcrumb](https://underglass.dev/docs/strata/components/breadcrumb) | `<nav>` around an `<ol>` of links | None (flat links) |
| [List](https://underglass.dev/docs/strata/components/list) | `<ul role="list">` of `<li>` rows | One raised slab; actionable rows are flat links or buttons |
| [MessageBar](https://underglass.dev/docs/strata/components/message-bar) | `<div role="status">` or `role="alert"` | A raised slab with an intent stripe |
| [Pagination](https://underglass.dev/docs/strata/components/pagination) | `<nav>` around page links or buttons | A row of small keys; the current page is held down |
| [Skeleton](https://underglass.dev/docs/strata/components/skeleton) | `<span aria-hidden>` placeholders | None (flat, shimmering) |
| [Tooltip](https://underglass.dev/docs/strata/components/tooltip) | `<div role="tooltip" popover>` | A small floating slab in the top layer |
| [Toast](https://underglass.dev/docs/strata/components/toast) | A `<section>` region with a `role="status"` list, from script | Floating MessageBars in the top layer |
| [Toolbar](https://underglass.dev/docs/strata/components/toolbar) | `<div role="toolbar">` | Keys on one plinth, one tab stop |
| [Table](https://underglass.dev/docs/strata/components/table) | `<table>` with `<caption>` and sortable headers | One raised slab; rows are flat |
| [Tabs](https://underglass.dev/docs/strata/components/tabs) | `<button role="tab">` in a `role="tablist"` | Flat tabs over a rail groove; the selected tab's indicator is a mark in it; `form="rail"`: latching keys on one plinth with an LED each ([Rail form](https://underglass.dev/docs/strata/components/tabs#11-rail-form-rail)) |

## Tier C

| Component | Native element | Object |
| --- | --- | --- |
| [SegmentedControl](https://underglass.dev/docs/strata/components/segmented-control) | Native radios in a `<fieldset>` | Keys on one plinth; the selected key is held down; `form="latching"`: interlocking latching keys with an LED each ([Latching form](https://underglass.dev/docs/strata/components/segmented-control#11-latching-form-latching)) |
| [Rating](https://underglass.dev/docs/strata/components/rating) | Native radios in a `<fieldset>`; a `role="img"` display | Stars printed on the panel (captured, no relief) |
| [Stepper](https://underglass.dev/docs/strata/components/stepper) | An `<ol>` with `aria-current="step"` | Coins on a groove; steps to come are flat |
| [NavigationRail](https://underglass.dev/docs/strata/components/navigation-rail) | A `<nav>` with a list of links, `aria-current="page"` | Keys on a raised slab down the start edge |
| [Popover](https://underglass.dev/docs/strata/components/popover) | `<div popover role="dialog">` opened by a `<button popovertarget>` | A floating slab in the top layer |
| [TreeView](https://underglass.dev/docs/strata/components/tree-view) | `<ul role="tree">` of nested `treeitem`s | One raised slab; rows are flat |
| [Carousel](https://underglass.dev/docs/strata/components/carousel) | A `<section aria-roledescription="carousel">` of slides, with buttons | Captured slides in a frame, keys under it |
| [Menu](https://underglass.dev/docs/strata/components/menu) | `<div popover role="menu">` of `menuitem` buttons, opened by a menu button | A floating slab with flat rows |
| [Combobox](https://underglass.dev/docs/strata/components/combobox) | `<input list>` with a `<datalist>`; the browser's own list | A TextField well with a printed chevron |
| [DatePicker](https://underglass.dev/docs/strata/components/date-picker) | `<input type="date">`; the browser's own calendar | A TextField well with a printed calendar |

## Instrument

The [Instrument level](https://github.com/RaananW/underglass/blob/main/docs/ui-library/instrument.md)'s components: hardware objects over native controls, at every presentation.

| Component | Native element | Object |
| --- | --- | --- |
| [Knob](https://underglass.dev/docs/strata/components/knob) | `<input type="range">` over a printed dial | A skirt and a cap with a turning pointer, a scale printed on the face |
| [Fader](https://underglass.dev/docs/strata/components/fader) | `<input type="range">`, vertical (`writing-mode: vertical-lr`) or horizontal, its thumb the carriage | A slot in the faceplate with a capped carriage, a scale printed beside it |
| [JogWheel](https://underglass.dev/docs/strata/components/jog-wheel) | `<input type="range">` over a flat wheel; `wrap` makes the value go round | A wheel in a bearing recess with a finger dimple that turns on an accumulated angle (never back), coasting after a flick on `spring.jog` |
| [PatchPoint, PatchBay](https://underglass.dev/docs/strata/components/patch-point) | `<input type="checkbox">` (or a `<button aria-pressed>`) per jack; a bay is a `<fieldset>` | A jack in a washer; connected, a plug stands out of the hole with a short cable; an optional LED |
| [RotarySelector](https://underglass.dev/docs/strata/components/rotary-selector) | `<select>` over a printed dial, one detent per `<option>` | A knob that turns to the chosen option, the options' labels printed round it |
| [Lamp](https://underglass.dev/docs/strata/components/lamp) | `<input type="checkbox" role="switch">` in its label row, or a `<button aria-pressed>` when `momentary` | A lens on a bezel: dark glass off, glowing and emitting on |
| [StatusLight](https://underglass.dev/docs/strata/components/status-light) | `<span role="img" aria-label>`, a `<span>` with its label, or a live `<output>` | A small lens with an emitter; `colour` a role, `blink` a tempo token |
| [Meter](https://underglass.dev/docs/strata/components/meter) | `<meter>` (role `meter`) with `min`, `max`, `low`, `high`, `optimum` | A bar of LED segments lit from the value (each an emitter, in its zone's colour), or a needle on a printed arc on `spring.meter`; a held `peak` |
| [Gauge](https://underglass.dev/docs/strata/components/gauge) | `<meter>` (a bounded measurement; not `<progress>`) | A round dial under glass: a needle on `spring.gauge` over a printed scale, a red zone from `high` |
| [Display](https://underglass.dev/docs/strata/components/display) | The TextField's `<input>` as `form="display"`, or a read-only `<output>` | A glass window in a bezel over the printed text, backlit by emitters (`backlight` a colour role); the text stays captured content; `segments`: the text in a seven-segment face with the unlit segments faintly printed ([section 11](https://underglass.dev/docs/strata/components/display#11-the-segments-look-a-seven-segment-face)) |
| [Pad, PadGrid](https://underglass.dev/docs/strata/components/pad) | `<button>`, with `aria-pressed` when latching; a grid is a `<div role="group">` | A square soft cap in a grid, a lit rim under it: dark off, glowing and emitting while struck or latched; the cap travels |
| [Keypad](https://underglass.dev/docs/strata/components/keypad) | A `<fieldset>` of `<button>`s, the Grid navigation pattern for the arrows | Machined square caps with printed legends on one polished plinth; each key travels |
