Skip to content
Components

Selection controls

Checkbox for independent facts, radio for mutually exclusive answers, switch only for something that takes effect immediately.

Checkbox

The real input is present and merely visually hidden, never replaced by a role="checkbox" div. A div gets you no Space key, no form submission, and no :indeterminate.
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

Radios in one group share a `name`. Without it they are independent checkboxes that happen to look round — and the arrow-key navigation that makes a group work silently does not exist.
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

A row's own <label> names the switch. Where there is no visible label beside it, pass `label` instead.
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

PropTypeDefault
modelValuebooleanfalse

Checked, as `v-model`. It is the real `<input>`'s value — the control is not a div wearing a role.

indeterminatebooleanfalse

Some 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.

disabledbooleanfalse

Inert and unfocusable. Prefer leaving the control live and explaining what is missing.

Slots

default

The 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:modelValueboolean

The native input's change, forwarded.

GdRadio

Props

PropTypeDefault
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.

disabledbooleanfalse

Inert and unfocusable.

Slots

default

The label, inside the `<label>` with the input.

Events

update:modelValuestring | number

The chosen `value`, when this option is selected.

GdSwitch

Props

PropTypeDefault
modelValuebooleanfalse

On or off, as `v-model`. Drawn from `aria-checked`, so the look and the announcement cannot disagree.

disabledbooleanfalse

Inert 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:modelValueboolean

Emitted 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 name attribute 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 disabled attribute 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.

Navigate

Esc