COMPONENT
Choice
Checkbox, radio and switch. Real inputs with their paint replaced — never a span pretending to be a control.
All three, in every state
Tab through them. They check with the keyboard, they submit with a form, and they announce themselves, because they are the real elements.
<div class="choice-group">
<span class="field-label">CHECKBOX</span>
<label class="choice"><input class="checkbox" type="checkbox"><span class="choice-label">Fixed scope</span></label>
<label class="choice"><input class="checkbox" type="checkbox" checked><span class="choice-label">Weekly builds</span></label>
<label class="choice"><input class="checkbox" type="checkbox" data-indeterminate><span class="choice-label">Indeterminate</span></label>
<label class="choice"><input class="checkbox" type="checkbox" disabled><span class="choice-label">Unavailable</span></label>
</div>
<div class="choice-group">
<span class="field-label">RADIO</span>
<label class="choice"><input class="radio" type="radio" name="engagement" checked><span class="choice-label">Project</span></label>
<label class="choice"><input class="radio" type="radio" name="engagement"><span class="choice-label">Retainer</span></label>
<label class="choice"><input class="radio" type="radio" name="engagement"><span class="choice-label">Advisory</span></label>
</div>
<div class="choice-group">
<span class="field-label">SWITCH</span>
<label class="choice"><input class="switch" type="checkbox" checked><span class="choice-label">On</span></label>
<label class="choice"><input class="switch" type="checkbox"><span class="choice-label">Off</span></label>
<label class="choice"><input class="switch" type="checkbox" disabled><span class="choice-label">Disabled</span></label>
</div>Reference
Read from components/choice.css when this page was built, so it cannot fall behind the stylesheet.
.choice.choice-label.checkbox.radio.switch.choice-group--ds-accent--ds-accent-deep--ds-control-h--ds-cream--ds-focus-ring--ds-focus-width--ds-font-body--ds-gap-loose--ds-ground--ds-hairline--ds-hit-min--ds-ink-disabled--ds-ink-faint--ds-ink-on-cream--ds-ink-read--ds-motion-fast--ds-motion-travel--ds-radio-dot--ds-radius-field--ds-radius-pill--ds-radius-round--ds-rule--ds-rule-strong--ds-sunk--ds-switch-inset--ds-switch-knob--ds-switch-travel--ds-switch-w--ds-text-control--ds-tick-bar--ds-tick-h--ds-tick-size--ds-tick-stroke--ds-tick-wNotes
The design these came from drew them as decorative markup, which is the right answer for a static mock-up. A design system may not: a styled span has no keyboard behaviour, no form value, no announced role and no indeterminate state, and every one of those has to be reinvented in JavaScript by whoever uses it.
appearance: none keeps the element and takes only its paint. The label wraps the input, so the text is part of the hit area without a for/id pair that can silently drift apart.
The indeterminate checkbox above is set from script, because :indeterminate is a DOM state that cannot be expressed in HTML at all — the one thing on this page the specimen has to fake.