Radio
The Radio component allows users to select a single option from a group of mutually exclusive choices, with proper form integration and accessibility support.
Usage
import { Radio, RadioGroup, RadioSize } from 'blend-v1' function MyComponent() { const [selectedOption, setSelectedOption] = useState('option1') return ( <RadioGroup name="options" value={selectedOption} onChange={setSelectedOption} label="Select an option" > <Radio value="option1" size={RadioSize.MEDIUM}> Option 1 </Radio> <Radio value="option2" size={RadioSize.MEDIUM}> Option 2 </Radio> <Radio value="option3" size={RadioSize.MEDIUM}> Option 3 </Radio> </RadioGroup> ) }
API Reference
Radio Props
Prop Name | Type |
---|---|
id | string |
value | string |
checked | boolean |
defaultChecked | boolean |
onChange | (checked: boolean) => void |
disabled | boolean |
required | boolean |
error | boolean |
size | RadioSize |
children | ReactNode |
subtext | string |
slot | ReactNode |
name | string |
RadioGroup Props
Prop Name | Type |
---|---|
id | string |
label | string |
name | string |
defaultValue | string |
value | string |
children | ReactNode |
onChange | (value: string) => void |
disabled | boolean |
Features
- Two size variants (small, medium)
- Radio group management with automatic selection
- Optional subtext for additional context
- Optional slot for badges, icons, or other elements
- Required field indicator (asterisk)
- Error state styling
- Disabled state support
- Controlled and uncontrolled modes
- Accessible by default
- Built on native HTML radio inputs
- Customizable styling through tokens
Usage Examples
Basic Radio Group
Simple radio group with multiple options
import { Radio, RadioGroup } from 'blend-v1' function MyComponent() { const [selectedOption, setSelectedOption] = useState('option1') return ( <RadioGroup name="options" value={selectedOption} onChange={setSelectedOption} label="Select an option" > <Radio value="option1">Option 1</Radio> <Radio value="option2">Option 2</Radio> <Radio value="option3">Option 3</Radio> </RadioGroup> ) }
Radio with Subtext
Radio buttons with additional descriptive text
<RadioGroup name="size-options" value={selectedSize} onChange={setSelectedSize} label="Choose your size" > <Radio value="small" subtext="Perfect for small spaces"> Small </Radio> <Radio value="medium" subtext="Standard size for most use cases"> Medium </Radio> <Radio value="large" subtext="Ideal for large displays"> Large </Radio> </RadioGroup>
Radio with Slots
Radio buttons with additional elements (badges, icons, etc.)
<RadioGroup name="theme-options" value={selectedTheme} onChange={setSelectedTheme} label="Choose your theme" > <Radio value="light" slot={<span>☀️</span>}> Light Theme </Radio> <Radio value="dark" slot={<span>🌙</span>}> Dark Theme </Radio> <Radio value="auto" slot={<span>🔄</span>} subtext="Follows system preference" > Auto Theme </Radio> </RadioGroup>
Different Sizes
Radio buttons with different size variants
// Small size <RadioGroup name="small-size" value={selectedOption} onChange={setSelectedOption}> <Radio value="option1" size={RadioSize.SMALL}> Small Option 1 </Radio> <Radio value="option2" size={RadioSize.SMALL}> Small Option 2 </Radio> </RadioGroup> // Medium size (default) <RadioGroup name="medium-size" value={selectedOption} onChange={setSelectedOption}> <Radio value="option1" size={RadioSize.MEDIUM}> Medium Option 1 </Radio> <Radio value="option2" size={RadioSize.MEDIUM}> Medium Option 2 </Radio> </RadioGroup>
Radio States
Radio buttons in various states
<RadioGroup name="states" value={selectedOption} onChange={setSelectedOption}> <Radio value="normal">Normal state</Radio> <Radio value="required" required={true}> Required field </Radio> <Radio value="disabled" disabled={true}> Disabled option </Radio> <Radio value="error" error={true}> Error state </Radio> </RadioGroup>
Controlled vs Uncontrolled
Radio groups with different state management approaches
// Controlled radio group const [selectedValue, setSelectedValue] = useState("option1"); <RadioGroup name="controlled" value={selectedValue} onChange={setSelectedValue} label="Controlled Group" > <Radio value="option1">Option 1</Radio> <Radio value="option2">Option 2</Radio> </RadioGroup> // Uncontrolled radio group <RadioGroup name="uncontrolled" defaultValue="option1" label="Uncontrolled Group" > <Radio value="option1">Option 1</Radio> <Radio value="option2">Option 2</Radio> </RadioGroup>
Individual Radio Controls
Radio buttons used outside of a group
const [selectedIndividual, setSelectedIndividual] = useState("individual1"); <Radio value="individual1" name="individual" checked={selectedIndividual === "individual1"} onChange={(checked) => checked && setSelectedIndividual("individual1")} > Individual Radio 1 </Radio> <Radio value="individual2" name="individual" checked={selectedIndividual === "individual2"} onChange={(checked) => checked && setSelectedIndividual("individual2")} subtext="This is an individual radio control" > Individual Radio 2 </Radio>
Complex Form Example
Complete form with radio group
function SubscriptionForm() { const [selectedPlan, setSelectedPlan] = useState('basic') return ( <div className="space-y-4"> <h3 className="text-lg font-semibold">Subscription Plan</h3> <RadioGroup name="subscription-plan" value={selectedPlan} onChange={setSelectedPlan} label="Choose your plan" > <Radio value="basic" subtext="Perfect for individuals and small projects" slot={<span className="text-green-500 text-sm">Free</span>} > Basic Plan </Radio> <Radio value="pro" subtext="Advanced features for growing teams" slot={<span className="text-blue-500 text-sm">$9/mo</span>} > Pro Plan </Radio> <Radio value="enterprise" subtext="Custom solutions for large organizations" slot={ <span className="text-purple-500 text-sm">Custom</span> } > Enterprise Plan </Radio> </RadioGroup> </div> ) }
Disabled Radio Group
Radio group with all options disabled
<RadioGroup name="disabled-group" value={selectedOption} onChange={setSelectedOption} label="Disabled Options" disabled={true} > <Radio value="option1">Option 1</Radio> <Radio value="option2">Option 2</Radio> <Radio value="option3">Option 3</Radio> </RadioGroup>
Component Tokens
You can style the radio component using the following tokens:
export type RadioSize = 'sm' | 'md' export type RadioState = 'default' | 'hover' | 'disabled' | 'error' export type RadioIndicatorState = 'active' | 'inactive' export type RadioTokensType = { gap: CSSObject['gap'] slotGap: CSSObject['gap'] groupGap: CSSObject['gap'] indicator: { [key in RadioIndicatorState]: { background: { [key in Exclude< RadioState, 'error' >]: CSSObject['backgroundColor'] } border: { [key in Exclude<RadioState, 'error'>]: CSSObject['borderColor'] } } } activeIndicator: { active: { background: { [key in Exclude< RadioState, 'hover' | 'error' >]: CSSObject['backgroundColor'] } } } content: { label: { color: { [key in RadioState]: CSSObject['color'] } font: { [key in RadioSize]: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] } } } sublabel: { color: { [key in RadioState]: CSSObject['color'] } font: { [key in RadioSize]: { fontSize: CSSObject['fontSize'] fontWeight: CSSObject['fontWeight'] } } } } height: { [key in RadioSize]: CSSObject['height'] } borderWidth: { [key in RadioIndicatorState]: { [key in Exclude<RadioState, 'error'>]: number } } slot: { size: { [key in RadioSize]: CSSObject['width'] } } }
Enums
RadioSize
enum RadioSize { SMALL = 'sm', MEDIUM = 'md', }
Type Definitions
RadioState
type RadioState = 'default' | 'hover' | 'disabled' | 'error'
RadioIndicatorState
type RadioIndicatorState = 'active' | 'inactive'
Accessibility Features
The Radio component includes several accessibility features:
- Proper ARIA attributes: Uses appropriate ARIA roles and states
- Keyboard navigation: Supports keyboard interaction (Arrow keys, Space, Enter)
- Screen reader support: Proper labeling and announcements
- Focus management: Clear focus indicators and keyboard focus
- Required field indication: Visual and programmatic indication of required fields
- Error state communication: Clear error state communication to assistive technologies
- Group semantics: Proper radio group semantics for screen readers
- Mutual exclusivity: Ensures only one option can be selected within a group