Radio Group allows users to select exactly one option from a set of mutually exclusive choices. It provides a fieldset container with legend and individual radio buttons.
Installation
yarn add @twilio-paste/radio-group
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
const MyComponent = () => {
const [value, setValue] = React.useState('option1');
return (
<RadioGroup
name="example"
legend="Choose an option"
value={value}
onChange={(newValue) => setValue(newValue)}
>
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
<Radio value="option3">Option 3</Radio>
</RadioGroup>
);
};
RadioGroup Props
Name for all radio buttons in the group. Required for form submission.
legend
string | React.ReactNode
required
Label for the radio group, displayed as a fieldset legend.
Collection of Radio components.
The currently selected radio value (controlled component).
Callback fired when the selected value changes. Receives the new value as a string.
Disables all radio buttons in the group.
Marks the radio group as required for validation.
Error message displayed below the group with error styling.
Additional help text displayed below the group.
orientation
'vertical' | 'horizontal'
default:"'vertical'"
Layout direction for the radio buttons.
i18nRequiredLabel
string
default:"'(required)'"
Label text for the required indicator, useful for internationalization.
element
string
default:"'RADIO_GROUP'"
Overrides the default element name for customization.
Radio Props
The value of this radio option.
Label text for the radio button.
ID for the radio input. Auto-generated if not provided.
Disables this specific radio button.
Help text displayed below this radio option.
Examples
Basic Radio Group
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
const [plan, setPlan] = React.useState('starter');
<RadioGroup
name="plan"
legend="Select a plan"
value={plan}
onChange={setPlan}
>
<Radio value="starter">Starter - $10/month</Radio>
<Radio value="professional">Professional - $25/month</Radio>
<Radio value="enterprise">Enterprise - Custom pricing</Radio>
</RadioGroup>
With Help Text
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
<RadioGroup
name="delivery"
legend="Delivery method"
helpText="Choose how you'd like to receive your order"
>
<Radio value="standard" helpText="5-7 business days">
Standard shipping
</Radio>
<Radio value="express" helpText="2-3 business days">
Express shipping
</Radio>
<Radio value="overnight" helpText="Next business day">
Overnight shipping
</Radio>
</RadioGroup>
Required with Error
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
<RadioGroup
name="priority"
legend="Priority level"
required
errorText="Please select a priority level to continue"
>
<Radio value="low">Low</Radio>
<Radio value="medium">Medium</Radio>
<Radio value="high">High</Radio>
</RadioGroup>
Horizontal Layout
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
<RadioGroup
name="size"
legend="T-shirt size"
orientation="horizontal"
>
<Radio value="small">S</Radio>
<Radio value="medium">M</Radio>
<Radio value="large">L</Radio>
<Radio value="xlarge">XL</Radio>
</RadioGroup>
With Disabled Options
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
<RadioGroup
name="availability"
legend="Choose a time slot"
>
<Radio value="morning">Morning (9am - 12pm)</Radio>
<Radio value="afternoon" disabled>
Afternoon (12pm - 5pm) - Fully booked
</Radio>
<Radio value="evening">Evening (5pm - 8pm)</Radio>
</RadioGroup>
Controlled Component
import { RadioGroup, Radio } from '@twilio-paste/radio-group';
const [paymentMethod, setPaymentMethod] = React.useState('');
const handlePaymentChange = (value: string) => {
setPaymentMethod(value);
// Additional logic when selection changes
console.log('Payment method selected:', value);
};
<RadioGroup
name="payment"
legend="Payment method"
value={paymentMethod}
onChange={handlePaymentChange}
required
>
<Radio value="credit">Credit card</Radio>
<Radio value="debit">Debit card</Radio>
<Radio value="paypal">PayPal</Radio>
</RadioGroup>
Accessibility
- Uses semantic fieldset and legend elements for proper grouping
- Each Radio has a visible label via the children prop
- Supports full keyboard navigation (Arrow keys, Tab, Space)
- Required groups show a RequiredDot with accessible label
- Help text and error messages are properly associated
- Only one radio can be selected at a time within a group
- Disabled state is announced to screen readers
- Error state uses aria-invalid for screen reader announcements
Best Practices
- Use Radio Group for mutually exclusive options (only one can be selected)
- For multiple selections, use Checkbox Group instead
- Provide at least 2 options, maximum recommended is 5-7 options
- For more than 7 options, consider using a Select instead
- Keep radio labels concise and descriptive
- Always provide a clear legend for the group
- Use vertical orientation by default for better scannability
- Use horizontal orientation only for short, simple options (like Yes/No)
- Provide helpful error messages when validation fails
- Consider default selection for better UX, especially for required fields