--- title: RadioGroup description: Manage a single selection across a set of radio options. --- import { StoryEmbed } from '/snippets/ui/StoryEmbed.mdx'; import RadioGroupReference from '/snippets/ui/generated/input/radio-group.mdx'; `RadioGroup` coordinates the value, keyboard navigation, and form submission of its [Radio](/ui/primitives/input/radio) children. ## Anatomy Put each `Radio` inside the group and associate it with a label. `RadioGroup` and `Radio` are separate exports. ```text fieldset ├── legend └── RadioGroup ├── label │ └── Radio └── label └── Radio ``` | Part | Requirement | Purpose | | -------------------- | --------------------------- | ---------------------------------------------------------- | | `RadioGroup` | Required | Owns selection, keyboard navigation, and form integration. | | `Radio` | One per option | Supplies an option with a distinct `value`. | | `label` | Recommended for each option | Provides a visible, clickable name for its radio. | | `fieldset`, `legend` | Optional grouping | Groups related controls under a visible heading. | Give the group its own accessible name using `aria-label` or `aria-labelledby`. In the examples below, `aria-labelledby` connects the group to the legend. Each radio also needs its own name. Put selection props on `RadioGroup` and option values on `Radio`. ## Uncontrolled state Use `defaultValue` to set the initial billing frequency. The group owns subsequent changes. ```tsx import { useId } from 'react'; import { Radio, RadioGroup } from 'twenty-ui/primitives/input'; export const BillingFrequency = () => { const labelId = useId(); return (
Billing frequency
); }; ``` The group's `name` identifies the selected value in form submission. Give the group an accessible name as well as labeling each radio. ## Controlled state Pass `value` and update it with `onValueChange` to own the same billing frequency in React state. Selection belongs to the group, not to individual radio controls. ```tsx import { useId, useState } from 'react'; import { Radio, RadioGroup } from 'twenty-ui/primitives/input'; export const BillingFrequency = () => { const labelId = useId(); const [billingFrequency, setBillingFrequency] = useState('monthly'); return (
Billing frequency
); }; ``` `onValueChange` receives the next value and event details. The generic value type is inferred from the props. Use `disabled` on the group to disable every option, or on an individual radio to disable one choice. Arrow keys navigate the enabled options; Tab moves out of the group. ## Props The reference is generated from the public component types. Native attributes, including accessible names and event handlers, are also accepted on parts that render elements.