Selection controls
Checkbox for independent facts, radio for mutually exclusive answers, switch only for something that takes effect immediately.
Checkbox
Code
<GdCheckbox v-model="overlays">Show mapped overlays</GdCheckbox>
<GdCheckbox v-model="partial" indeterminate>Some children on</GdCheckbox>
<GdCheckbox :model-value="false" disabled>Unavailable in this council</GdCheckbox>Radio
Code
<GdRadio v-model="mode" name="search-mode" value="explore">Explore uses</GdRadio>
<GdRadio v-model="mode" name="search-mode" value="specific">Something specific</GdRadio>Switch
Code
<label class="row">
<span>Show flood overlay</span>
<GdSwitch v-model="flood" />
</label>
<GdSwitch v-model="flood" label="Show flood overlay" /> <!-- no visible label -->API
GdCheckbox
Props
modelValuebooleanfalseChecked, as `v-model`. It is the real `<input>`'s value — the control is not a div wearing a role.
indeterminatebooleanfalseSome children on, some off. Sets the visual AND the DOM's `input.indeterminate`, which has no HTML attribute and so has to be written to the element.
disabledbooleanfalseInert and unfocusable. Prefer leaving the control live and explaining what is missing.
Slots
defaultThe label. It sits inside the `<label>`, so the words are part of the target — which is also how an 18px box clears 44px.
Events
update:modelValuebooleanThe native input's change, forwarded.
GdRadio
Props
modelValuestring | number—The group's selected value, as `v-model`. No default — an unset group is a real state, and every radio in the group binds the same model.
valuerequiredstring | number—What this option is worth when chosen.
namerequiredstring—The group. Required: without a shared name they are independent checkboxes that happen to look round, and the arrow-key navigation silently does not exist.
disabledbooleanfalseInert and unfocusable.
Slots
defaultThe label, inside the `<label>` with the input.
Events
update:modelValuestring | numberThe chosen `value`, when this option is selected.
GdSwitch
Props
modelValuebooleanfalseOn or off, as `v-model`. Drawn from `aria-checked`, so the look and the announcement cannot disagree.
disabledbooleanfalseInert and unfocusable.
labelstring—The accessible name, for a switch with no visible label beside it. A switch in a row with its own `<label>` does not need this.
Events
update:modelValuebooleanEmitted on click. The switch has no slots — it is a bare `<button role="switch">`.
Usage Guidelines
Do
- Use a checkbox for independent facts. Several can be true at once, and the change usually waits for a Save.
- Use a radio for mutually exclusive answers (between two and five options).
- Use a switch for settings that take effect immediately (e.g., a map layer toggle).
- Group radios by giving every radio in a group the same
nameattribute for keyboard navigation.
Don't
- Don't use a switch if the form requires a Save button to apply changes. Use a checkbox instead.
- Don't use a radio group for more than five options. Use a Select component instead.
- Don't use the
disabledattribute to indicate "not yet available". Leave the control interactive and provide inline validation explaining what is missing.
Behavior & Anatomy
Accessibility Details
The switch component is a <button role="switch"> rather than a styled checkbox. This ensures screen readers announce "on" and "off" instead of "checked" and "not checked", which is critical for live state toggles.
The radio's ring
Selected is drawn as a thick ring rather than an inner dot: one property changes, so there is nothing to mis-centre at fractional pixel sizes.