Decisions

Living

The design and token decisions that shape the system, plus known limitations and what's deliberately deferred. This is the reader-facing companion to the governance record; it's updated as decisions land.


Locked decisions

Canonical focus ring

Every focus indicator uses color.interactive.focus (brand-400) via the -focus-ring-fill / -width / -offset token family. The older color.border.focus role is deprecated and has no consumers.

"Destructive", not "danger"

The high-consequence action variant is named vi-btn--destructive with --btn-destructive-* tokens. Its hover/active step resolves to error-800 through the token chain โ€” no filter hacks.

Surface vs background

color.surface.* (paired with contrast-checked color.on-surface.*) is the family for component and section fills. color.background.* stays for page-level roles.

Interactive vs decorative borders

Form controls use color.border.interactive (neutral-500, 4.8:1) so their boundary meets the 3:1 non-text contrast bar. Decorative containers like cards keep the lighter color.border.default โ€” a defined boundary matters more on something you type into than on a static panel.

Contrast-tuned placeholder

Placeholder text uses color.text.placeholder (neutral-500, 4.8:1). The disabled-text token (neutral-400) fails AA at text size, so placeholders get their own role rather than borrowing it.

Required fields use an asterisk

Required fields are marked with an asterisk (vi-field__required) in the label, not an "(optional)" label on everything else. The asterisk is decorative (aria-hidden); the real state is the control's required attribute, so colour is never the only cue.

Tier 3 glyph suffixes (signed off 2026-07-06)

Masked-SVG glyphs on a component use a -[glyph]-fill / -mask (optional -size) family: -fill is the color, -mask is a colorless SVG shape. Now locked in ยง5.

-caret-fill / -size / -maskSelectDropdown caret glyph
-check-fill / -maskCheckboxCheckmark glyph (radio uses a filled dot, no mask)

Known limitations & deferred

Placeholder brand palette

The current brand scale is an interim placeholder tuned for AA contrast, not the final VI palette. error-500 (~3.8:1) still fails AA for text-sized use and is logged for the real-palette milestone.

Focus ring on saturated brand backgrounds

The brand-400 focus ring meets 3:1 on white, subtle, and dark surfaces, but not on a saturated vi-section--brand fill. Resolves with the real palette.

Deferred by design

Checkbox indeterminate state (needs a dash glyph) and <select multiple> are out of scope for now. The Field component is otherwise complete: input, textarea, select, checkbox, and radio.