Design principles
Compact native desktop density
This is application chrome, not a marketing page. Controls are compact, information remains scannable, and vertical rhythm favors work over spectacle.
Surfaces establish hierarchy
Use backdrop, canvas, panel, raised, and overlay surfaces before adding outlines. A card, a popover, a dialog, and a menu are told apart from what is behind them by a colour step and an elevation, not by a line drawn around them.
“Borderless” does not mean “no hierarchy.” It means hierarchy should first come from surface, spacing, grouping, and elevation.
A line says something a surface cannot
Every line in the library has one of four meanings:
- a rule, which divides content sharing one surface. It is
foundation::rule, a child element rather than a border, so it can be inset and so a component that spends its border on focus can still draw one. It is painted ininteractive.divider; - a boundary a pointer acts on — a slider rail, a switch edge, a scrollbar
gutter, a resize seam. These are
interactive.trackandinteractive.hairlineStrong, and they carry the 3:1 non-text contrast the guidelines ask of a control boundary; - a report — focus, invalidity, a drop target, a refusal. These are state
marks in the colour of the thing being reported. Fields use paint-only
halos; a border-based report reserves its width while resting. Becoming
invalid must not reflow the row. Glass uses a paint-only inward report edge
in
interactive.focus, replacing its optical hairline rather than adding a halo outside the material.Glass::focusedandGlassSurface::focusedown that report; do not combine them withTheme::focus_ring_on; - control definition — an in-content editable or actionable surface has a
quiet
interactive.controlHairline, an opaquesurface.controlfill one tonal step from its container, and a one-pixel top inset highlight frominteractive.controlHighlight. This material says “this can be operated”; it is not a high-contrast outline. The definition edge stays below 3:1. Focus and invalidity preserve resting geometry. Editable field focus followseffect.fieldFocus: a halo (ring) or the hover fill without a focus shadow (fill). Invalidity retains its danger halo; other control focus is unchanged.
Content controls do not use Liquid Glass. Glass belongs to floating controls
and media captions. Raised selection knobs use elevation.raised shadows;
their selection remains a tonal fill, not an accent-coloured label by default.
Control radii are 8, grouped containers 12, and cards 12 or 16 logical pixels,
resolved from tokens; the padding between nested shapes preserves concentric
corners. Large action controls can use the capsule radius.
A rule and a divider are decorative and deliberately do not carry 3:1. A
theme whose hairline clears 3:1 against every surface has drawn an outline
around every card, table, and menu in the library. They instead carry a
documented floor: composited over each surface, a line must move it by at least
1.5 L*, which is what contrast::line_report checks and the token gate
enforces.
Selection is a tonal fill
Every collection in the library says which row it is on the same way: the
stronger neutral wash from interactive.selected carries the whole selected
shape. It consumes no layout, so arriving on a row moves nothing. The shared
recipe is SelectedFill::selected_fill.
Selection never adds an edge rail, underline, or outline. Those marks create a second decorative geometry beside a shape whose fill already has enough area to state the answer. A row, node, chip, or segment may strengthen its text or semantic tint as a second channel, but it remains one rounded filled shape.
Accent has limited area
Accent marks primary actions, keyboard focus, links, and compact selection chrome. It must not wash large application regions. Success, warning, danger, and info are semantic states, not decorative alternatives.
Geometry is semantic
- Window planes, edge-attached regions, and rows inside a collection stay square. They are part of the surface behind them rather than detached entities sitting on it.
- 5px: key caps and tiny controls.
- 8px: normal controls and menu rows.
- 12px: cards and popovers.
- 16px: dialogs and message bubbles.
- pill: badges and status dots.
Repeated semantic geometry is tokenized, and the outer entity consumes the role rather than reconstructing it from a raw value. One-off geometry may remain local. Flat and rounded therefore describe attachment, not two visual styles: a sidebar is flat because it is a window plane; a popover is rounded because it is a detached entity.
Production style has one authority
A component does not invent anonymous spacing, corner radius, type size, weight, theme-colour alpha, or reusable measure. It consumes the theme's typed tokens or a complete shared recipe. This applies to small values too: 2px is a spacing step when it separates content, not an exception because it is small; 360px is a measure when several explanatory surfaces share it, not four local widths that happen to agree.
Local values remain valid where tokenization would misstate ownership: chart topology, normalized data encoding, asset proportions, hit testing, algorithmic physics, and one component's layout geometry. Such values are named beside the algorithm they explain. Mathematical zero and one remain local endpoints. This boundary keeps themes fully retunable without turning the token document into a collection of arbitrary coordinates.
The token gate parses production Rust and enforces this distinction. It skips scenes and test fixtures, so examples can describe their own canvas while shipping components cannot quietly create a second style system.
State is complete
Interactive components define default, hover, pressed, selected, disabled, and focus behavior. Disabled means the action handler is absent, not merely faded.
Loading, empty, unavailable, error, and stale are visually and semantically different.
Motion supports continuity
Motion communicates where content came from and what changed. It never blocks input or moves surrounding layout unexpectedly. Repeating animation uses fixed slots so opacity and scale remain paint-local. GPUI reduced-motion behavior is honored rather than reimplemented per component.
Effects preserve structure
Frost and edge fades are structural paint effects:
- frost paints blur before the complete floating subtree in one layer;
- edge fade applies to primitives by distance to the scroll boundary;
- a scroll shadow is a gradient band of
backdrop, not a line: content that continues past an edge is a soft fact, and a hard rule there reads as a boundary that has been reached; - selection washes are painted inside and consume no layout space;
- non-macOS platforms use an opaque fallback instead of exposing the desktop through unsupported transparency.
Truth over optimistic appearance
The interface presents facts from the owning application layer. A click is not success. A request failure is not empty data. The last verified value may remain visible while refresh fails, but it must be marked stale.
Testability is part of the component
A native window has no DOM. Semantic identity, role, measured bounds, focus, disabled state, and selection are part of the user-facing interface. A control that cannot be named and reached by the semantic tree is incomplete.