Radio group
A radio group asks for exactly one answer from a short list. tk-radio-group holds the label and the value; each tk-radio is one option.
<tk-radio-group label="How should we contact you?" name="contact" required> <tk-radio value="email">Email</tk-radio> <tk-radio value="phone" helper="Weekdays, 9:00 to 17:00">Phone call</tk-radio> <tk-radio value="none">Don't contact me</tk-radio> </tk-radio-group>
Anatomy
| Part | What it is |
|---|---|
tk-radio-group |
the group and the form field; one Tab stop for all its options |
| group label | the legend: usually the question, required |
| group helper and error | under the group label, above the options |
| group default slot | the tk-radio items, stacked vertically |
tk-radio |
one option; works only inside a group |
| circle | 20px; a filled circle with a dot when selected |
| default slot | the option label, required; it is the option's accessible name |
| helper | an optional hint under the option label |
The whole row, circle and label, is one click target.
Value
The group's value is the selected option's value. Set it on the group to preselect an
option; empty means nothing is selected.
<tk-radio-group label="Theme" name="theme" value="system"> <tk-radio value="light">Light</tk-radio> <tk-radio value="dark">Dark</tk-radio> <tk-radio value="system">Match the system</tk-radio> </tk-radio-group>
- Put
name,value,required, anderroron the group, never on an option. - Leave questions unselected. In settings, show the current value.
- The group submits one
nameandvalue; nothing while nothing is selected.
States
<tk-radio-group label="Delivery" name="delivery" value="standard"> <tk-radio value="standard">Standard</tk-radio> <tk-radio value="express" helper="Not available for this address" disabled>Express</tk-radio> </tk-radio-group>
On hover, a selected circle's fill changes; an unselected circle stays the same. Keyboard focus shows a ring around the circle.
disabledon an option: grayed and skipped by the arrow keys. Say why in its helper, or leave the option out.disabledon the group: disables every option and removes the Tab stop. Selected and unselected disabled circles differ only by a faint dot, so if the locked choice matters, say it in text.
Required and error
<tk-radio-group label="Plan" name="plan" required error="Select a plan"> <tk-radio value="free">Free</tk-radio> <tk-radio value="team">Team</tk-radio> </tk-radio-group>
requiredblocks the form from submitting until an option is selected, and adds an asterisk.errorshows your message above the options, so it stays in view on a long list. It doesn't color any circle.- The group doesn't validate. You set
errorand clear it.
When to use
- Use a radio group when exactly one of 2 to 6 short options is valid. The choice applies when the form is submitted.
- Use a
Checkbox group when several answers can be valid. - Use a
Select for more than about 6 options or a tight space. - Use a
Segmented control to switch a view at once. Arrow keys select as they move, so a radio group must never act on its own. - Use a
Switch for one setting that's on or off, not two radios. - Use a
Selection card when each option needs a description, an image, or a price.
A user can't clear a radio group, only pick another option. If "none" is a fair answer, add it as an option, such as "None of the above".
Content
- Make the group label the question, in one sentence, sentence case.
- Keep option labels short, in sentence case, with no end punctuation. Each says what choosing it means.
- Keep a helper to one short sentence, with no full stop and no links.
- Write errors as "Select" and what it is, in the label's words: "Select a plan". For a yes or no question: "Select yes if you have a business account". No "please", no "invalid".
- Order options logically, alphabetically by default. Ordering by popularity can push people toward one answer.
- Let long labels wrap; don't truncate them.
More in
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Use a checkbox group when several answers apply | Force one answer with radios |
| Apply the choice when the form is submitted | Act on the selection as arrows move |
Set value on the group |
Put checked on an option |
| Keep 2 to 6 short options, stacked | List 10 options as radios; use a Select |
| Add "None of the above" as a real option | Expect users to clear a selection |
| Explain a disabled option, or leave it out | Disable an option with no reason |
Related
Checkbox : zero, one, or several options.Segmented control : one choice that switches a view at once.Select : one option from a long list.Selection card : a card around a radio, for richer options.Switch : an on/off setting that applies at once.
API
tk-radio-group attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
label |
string | the group label, required | |
label-hidden |
boolean | false |
hides the group label on screen, keeps the group name |
name |
string | the form field name, required | |
value |
string | '' |
the selected option's value; empty means none |
helper |
string | a hint under the group label | |
error |
string | the group error, above the options | |
required |
boolean | false |
blocks submit until an option is selected; adds an asterisk |
disabled |
boolean | false |
disables every option and removes the Tab stop |
tk-radio attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
value |
string | '' |
the submitted value, required; unique in the group |
helper |
string | a hint under the option label | |
disabled |
boolean | false |
grays the option; arrows skip it |
checked |
boolean | false |
read-only; the group sets it. Set the group's value instead |
Slots
| Element | Slot | Content |
|---|---|---|
tk-radio-group |
default | tk-radio items |
tk-radio |
default | the option label, required |
Events
tk-radio-group fires change when the user selects an option, including with the arrow
keys, not when your code sets value. Read the selection from value. form.reset()
restores the initial value without firing change. tk-radio fires no events.
Methods
tk-radio-group.focus() moves focus to the selected option, or the first enabled one.
CSS
tk-radio-group::part(group): the native<fieldset>.tk-radio::part(row): the circle and label row, the click target.
Tokens
| State | Circle border | Circle fill | Dot | Label |
|---|---|---|---|---|
| unselected | border/subtle |
surface/default |
text/default |
|
| selected | none | fill/accent; hover fill/accent/hover |
icon/accent/on-fill |
text/default |
| disabled | border/disabled |
surface/disabled |
icon/disabled |
text/disabled |
The focus ring is border/accent/focus. Helpers and the asterisk use text/secondary;
errors use text/error with icon/error. The circle is 20px with radius-full; the dot is
8px. Values per theme:
Accessibility
Built in:
- The group is announced as a radio group with its label and the number of options.
- The native radio keyboard: one Tab stop for the group, arrows move focus and selection, disabled options are skipped.
requiredanderrorare announced on the group. Errors start with a hidden "Error:".- Helpers and errors are read with their option or group.
- The row is at least 24px tall, and the focus ring is never hidden.
Your part:
- Don't act on a selection until the form is submitted.
- Offer "None of the above" when it's a fair answer; users can't clear a selection.
- If you mark fields with asterisks, explain them once per form: "* means required".
- Keep options in one column.
| Key | Action |
|---|---|
Tab |
moves focus into the group, to the selected option or the first one, and out again |
↓ / → |
selects the next option, wrapping to the first |
↑ / ← |
selects the previous option, wrapping to the last |
Space |
selects the focused option |
Contrast limits
- Unselected circle border: 1.33:1 in light and 2.00:1 in dark, under the 3:1 minimum; 4.22:1 in high contrast. It doesn't change on hover.
- Disabled circle: selected and unselected differ only by the dot, at 1.86:1 in light, 4.09:1 in dark, and 1.91:1 in high contrast.