Radio

A single choice from a set, with every option visible at once. A group that shows its options instead of hiding them in a field.

Usage

When to use Radio, how to build a group, and the decisions it leaves to you.

When to use

Radio asks for one value out of a set the reader can see all at once. It is a form field: the answer is submitted with the rest of the form, instead of changing how the page around it is drawn.
  • Two to about seven options, each short enough to read at a glance.
  • The set is fixed and known before the reader arrives, not typed, searched or paged.
  • Seeing the options beside each other is part of the decision: shipping speeds, plans, payment methods.
  • There is a sensible starting answer. A radio group can open on a default and usually should.
What to use instead. Pick by what the choice means, not by how it looks.
  • Select once the list stops fitting. Past roughly seven options, or once the labels wrap, the group takes too much space, and a field adds search, scrolling and a closed state.
  • Segmented when it is a view switch, not a form value. Segmented reads as a control on the page, and Radio reads as a field in a form.
  • A Checkbox group when more than one may be chosen. Radio also cannot say “none of these”: an optional single choice needs an explicit None option, or a Select with allowClear.
  • Tabs or a menu when choosing navigates somewhere: a different panel, a different URL, a different step.

Radio.Group against loose radios

Use Radio.Group for a set of radios. What turns a handful of radios into one control comes from the group, and a radio outside one gets none of it.
  • The shared name. The group generates one and gives it to every child. Loose radios have no name, so the browser never treats them as one group, and two can end up checked at once.
  • Selection comes from the group. A child is checked when its value is strictly equal to the group's. An object or array literal rebuilt on every render never matches itself, so give options primitive values (an id string) and keep the rich object in your own state.
  • disabled and block reach every child when you set them once on the group.
  • value is any. The group has no type parameter, and the RadioChangeEvent from onChange has an untyped target.value too. Type your own state and read the value through the event.

optionType and Radio.Button

One component, two looks. optionType defaults to "default", the dot, and "button" turns every child into a joined row of buttons. Radio.Button does the same for a single child.
  • Keep the dot in forms. It reads as a field, it stacks vertically without becoming a toolbar, and it leaves room for a description under each label.
  • Use optionType="button" where the set is compact and lives on one line: a toolbar, a table header, a filter row. One or two words per option.
  • buttonStyle picks between "outline" (the default) and "solid", which fills the selected button. It plays the role emphasis plays on other kit components, so Radio has no emphasis prop.
  • buttonStyle does nothing on the dot type. It styles the button wrapper, so it is inert until optionType says "button".
  • optionType on a single <Radio> warns in development and is ignored. It is a group prop.
  • There are no icons. The dot is drawn in CSS, so the icon pack has nothing to replace.

options against children

Two ways to fill a group, and they are not additive: options wins whenever it is not empty. The children are built from it, and whatever you passed as children is dropped without a warning.
  • options takes strings, numbers or objects. A bare string or number becomes both the value and the label, which is the shortest way to write a group.
  • The object form carries label, value, disabled, title, id, className, style, required and its own onChange. Nothing outside that list reaches the child.
  • Write children instead when an option needs more than a label: a description under the word, a price, a Tag, any layout of its own. label takes a node, but the option object still cannot reach the rest of the child.
  • Do not pass both. Children beside a filled options render nothing.

Size and layout

  • size only moves the button type. The dot's size comes from a token, so a size="small" group of dots looks the same as a default one. Change the radioSize token to resize the dot.
  • size is inherited, so a ConfigProvider or a wrapping component can set it for a whole form at once.
  • orientation="vertical" stacks the group. The older vertical boolean still works, and orientation wins when both are set.
  • Stack anything longer than three short labels, and anything where an option carries a description. A horizontal row of dots is hard to scan and the hit targets end up closer together than they read.
  • block makes the group fill its parent and share the width between its options. Use it on narrow surfaces and full-width cards.
  • With a title and a description, the dot centers on the whole label. Add items-start to the Radio and move the dot to the first line, as the With description and Card group examples on the Overview tab do.

Disabling one option against the whole group

Three layers apply in order: the child's own disabled, then the group's, then a surrounding Form or ConfigProvider.
  • Prefer disabling one option to disabling the group. A disabled group takes every radio out of the tab order, so a keyboard reader cannot reach it to find out what the choice even was.
  • A child only overrides the group by being explicit. Passing nothing inherits, so disabled={false} on one option of a disabled group is how you carve out the exception.
  • Under both, a disabled Form or ConfigProvider disables a radio that sets nothing itself.
  • Say why. A disabled option with no explanation beside it is a dead end: put the reason in the surrounding text, or wrap the option in a Tooltip, which still fires on a disabled label.
  • Do not let gray text be the only signal.

Inside a Form

A radio group is one field, so it belongs to one Form.Item with one name. Wrapping each radio in its own item is the common mistake, and it breaks the value and the grouping together.
  • Form.Item feeds value and onChange in, and reads target.value from the event for you.
  • The generated DOM name is seeded from the form item's own name path, so two groups for different fields on one page cannot collide and the name stays stable across renders. Pass name yourself only when something outside React has to match it, such as a native form post.
  • Validation belongs on the item, not on the group: rules={[{ required: true }]}. A group with no default value is empty, and that is the only state required can catch. Leave the default off when the answer is the reader's to give.
  • A radio inside a form item picks up the item's error state, with no selector of your own.
  • Give the group a visible label through the item's own label. The options are named by their text, and the group has no name until you give it one.