Form Controls
The raw input primitives that Form Field's label/hint/error wrapper composes: checkbox, radio, select, and label conventions. Native browser elements throughout — no custom-drawn checkbox/radio, per the product register's "don't reinvent standard affordances" rule. Styling is limited to accent-color (recolors the native control to the system's accent, still renders with the OS/browser's own shape) and layout (spacing, alignment).
Checkbox
Bare <input type="checkbox">, always paired with a <label> (wrapping, or via for) so the click target and screen-reader name aren't limited to the ~16px box. accent-color: var(--color-primary-vivid) is applied contextually (table row-selection, chip toggles) rather than globally, since a bare checkbox in a plain form (e.g. Terms & conditions agreement) is fine at the browser default.
Chip (checkbox, styled as a toggle)
Same <input type="checkbox">, wrapped in .chip for boolean filters and settings that read better as a pill than a bare checkbox row — see the component library for the full Chip entry alongside Status Badge and Pill.
Radio
.radio is layout only (inline label + control, gap, body-small text) — grouped via a shared name attribute, same as any native radio group. For a visually distinct card-style single-select (e.g. sale type), see the role="radio"/role="radiogroup" pattern in flows/sale-creation/details.html's Sale Type picker instead; that's a different component, not this one.
Select
Native <select>, styled identically to a text input via .field select (same border, radius, padding, focus ring) so it reads as part of the same input family rather than browser-default chrome. A bare <select> outside a .field wrapper (e.g. a table-cell type picker) still needs an explicit aria-label, since it has no visible <label> to associate with.
Label conventions
Every control gets a programmatically-associated name: a wrapping/for-linked <label> where a visible label fits, or an explicit aria-label where it doesn't (compact table-cell controls, icon-only buttons — see Button). title alone is never sufficient; it isn't reliably exposed to screen readers.
- Visible label available → wrap the control in
<label>(as in every example above), or use<label for="id">when the control can't be nested. - No room for a visible label (a table-cell select, a compact refund-amount input) →
aria-labeldescribing the control's specific row/context, e.g.aria-label="Refund type for Extended Warranty Add-on"(seeflows/order-refund/refund-review.html). - Required fields mark the label, not the input:
<span class="field__required">*</span>inside.field__label(see Form Field) — color is--color-primary, not danger; required-ness is a neutral marker, not a risk signal.