Overview
The Radio component provides accessible radio buttons with RadioGroup for managing selections. Supports multiple sizes, orientations, and descriptions. Built on React Aria Components for full keyboard navigation and screen reader support.
Import
import { Radio, RadioGroup } from 'stride-ds';
Basic Usage
import { Radio, RadioGroup } from 'stride-ds';
function Example() {
return (
<RadioGroup label="Choose your preferred option">
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
<Radio value="option3">Option 3</Radio>
</RadioGroup>
);
}
Orientation
Vertical (Default)
<RadioGroup label="Select size" orientation="vertical">
<Radio value="small">Small</Radio>
<Radio value="medium">Medium</Radio>
<Radio value="large">Large</Radio>
</RadioGroup>
Horizontal
<RadioGroup label="Select size" orientation="horizontal">
<Radio value="small">Small</Radio>
<Radio value="medium">Medium</Radio>
<Radio value="large">Large</Radio>
</RadioGroup>
Sizes
Three size options are available:
<RadioGroup label="Small Size" size="sm">
<Radio value="sm1" size="sm">Small Option 1</Radio>
<Radio value="sm2" size="sm">Small Option 2</Radio>
</RadioGroup>
<RadioGroup label="Medium Size" size="md">
<Radio value="md1" size="md">Medium Option 1</Radio>
<Radio value="md2" size="md">Medium Option 2</Radio>
</RadioGroup>
<RadioGroup label="Large Size" size="lg">
<Radio value="lg1" size="lg">Large Option 1</Radio>
<Radio value="lg2" size="lg">Large Option 2</Radio>
</RadioGroup>
With Descriptions
Add supporting text to radio options:
<RadioGroup
label="Choose your plan"
description="Select the plan that best fits your needs"
>
<Radio value="basic" description="Perfect for getting started">
Basic Plan
</Radio>
<Radio value="pro" description="Great for growing businesses">
Pro Plan
</Radio>
<Radio value="enterprise" description="Advanced features for large teams">
Enterprise Plan
</Radio>
</RadioGroup>
States
Default Value
<RadioGroup label="Choose option" defaultValue="option1">
<Radio value="option1">Selected by default</Radio>
<Radio value="option2">Option 2</Radio>
</RadioGroup>
Disabled
<RadioGroup label="Disabled Group" isDisabled defaultValue="option1">
<Radio value="option1">Disabled Selected</Radio>
<Radio value="option2">Disabled Unselected</Radio>
</RadioGroup>
Required
<RadioGroup label="Required Field" isRequired>
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
</RadioGroup>
With Error
<RadioGroup
label="Choose your preference"
errorMessage="Please select an option"
isInvalid
>
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
</RadioGroup>
RadioGroup Props
Label for the radio group.
Description text displayed below the label.
Error message displayed when isInvalid is true.
orientation
'horizontal' | 'vertical'
default:"'vertical'"
Layout direction of the radio buttons.
size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the radio buttons in the group.
The currently selected value (controlled).
The initially selected value (uncontrolled).
Handler called when the selection changes.
Whether the entire radio group is disabled.
Whether a selection is required.
Whether the radio group is in an invalid state.
Additional CSS classes to apply.
Radio Props
The value of this radio button.
The label text for the radio button.
Additional description text displayed below the label.
size
'sm' | 'md' | 'lg'
default:"'md'"
Size of the radio button. Inherits from RadioGroup if not specified.
Whether this specific radio button is disabled.
Additional CSS classes to apply.
Accessibility
The Radio components are built with React Aria Components and provide:
- Keyboard Navigation: Arrow keys to navigate between options, Space to select
- Focus Management: Proper focus handling and roving tabindex
- Screen Reader Support: Proper ARIA attributes and role=“radiogroup”
- Group Labeling: Automatic association between group label and radios
- Required/Invalid States: Properly announced to assistive technologies
Best Practices
-
Always provide a
label for the RadioGroup:
<RadioGroup label="Choose an option">
{/* radios */}
</RadioGroup>
-
Use meaningful
value attributes:
<Radio value="small">Small</Radio>
<Radio value="medium">Medium</Radio>
-
Add descriptions for complex choices:
<Radio value="pro" description="Includes all features">
Pro Plan
</Radio>
Examples
Subscription Plan Selector
import { RadioGroup, Radio } from 'stride-ds';
function PlanSelector() {
return (
<RadioGroup
label="Subscription Plan"
description="Choose the plan that works best for you"
defaultValue="pro"
>
<Radio value="free" description="Free forever with basic features">
Free Plan - $0/month
</Radio>
<Radio value="pro" description="Everything in Free plus advanced analytics">
Pro Plan - $19/month
</Radio>
<Radio value="enterprise" description="Everything in Pro plus priority support">
Enterprise - $99/month
</Radio>
</RadioGroup>
);
}
<RadioGroup
label="Size"
orientation="horizontal"
defaultValue="medium"
>
<Radio value="small">S</Radio>
<Radio value="medium">M</Radio>
<Radio value="large">L</Radio>
<Radio value="xlarge">XL</Radio>
</RadioGroup>
All States
<div className="space-y-8">
<RadioGroup label="Default State" defaultValue="option1">
<Radio value="option1">Selected Option</Radio>
<Radio value="option2">Unselected Option</Radio>
</RadioGroup>
<RadioGroup label="Disabled State" isDisabled defaultValue="disabled1">
<Radio value="disabled1">Disabled Selected</Radio>
<Radio value="disabled2">Disabled Unselected</Radio>
</RadioGroup>
<RadioGroup label="Required Field" isRequired>
<Radio value="req1">Required Option 1</Radio>
<Radio value="req2">Required Option 2</Radio>
</RadioGroup>
<RadioGroup
label="With Error"
isInvalid
errorMessage="Please select an option"
>
<Radio value="err1">Option 1</Radio>
<Radio value="err2">Option 2</Radio>
</RadioGroup>
</div>
Controlled Component
import { useState } from 'react';
import { RadioGroup, Radio } from 'stride-ds';
function ControlledExample() {
const [selected, setSelected] = useState('option1');
return (
<div>
<RadioGroup
label="Controlled Radio Group"
value={selected}
onChange={setSelected}
>
<Radio value="option1">Option 1</Radio>
<Radio value="option2">Option 2</Radio>
<Radio value="option3">Option 3</Radio>
</RadioGroup>
<p className="mt-4">Selected: {selected}</p>
</div>
);
}
The Radio components work with React Hook Form:
import { useForm, Controller } from 'react-hook-form';
import { RadioGroup, Radio } from 'stride-ds';
function FormExample() {
const { control, handleSubmit, formState: { errors } } = useForm();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="plan"
control={control}
rules={{ required: 'Please select a plan' }}
render={({ field }) => (
<RadioGroup
label="Choose a plan"
value={field.value}
onChange={field.onChange}
isInvalid={!!errors.plan}
errorMessage={errors.plan?.message}
>
<Radio value="free">Free</Radio>
<Radio value="pro">Pro</Radio>
<Radio value="enterprise">Enterprise</Radio>
</RadioGroup>
)}
/>
</form>
);
}