Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { RadioGroup } from '@/components/ui/radio';
import React, { useState } from 'react';
export function RadioDemo() {
const [value, setValue] = useState('option1');
return (
<RadioGroup
options={[
{ label: 'Default', value: 'option1' },
{ label: 'Comfortable', value: 'option2' },
{ label: 'Compact', value: 'option3' },
]}
value={value}
onValueChange={setValue}
/>
);
}
Installation
pnpm dlx bna-ui add radio
Usage
import { RadioGroup, RadioButton } from '@/components/ui/radio';
const [value, setValue] = useState('option1');
<RadioGroup
options={[
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
{ label: 'Option 3', value: 'option3' },
]}
value={value}
onValueChange={setValue}
/>;
Examples
Default
import { RadioGroup } from '@/components/ui/radio';
import React, { useState } from 'react';
export function RadioDemo() {
const [value, setValue] = useState('option1');
return (
<RadioGroup
options={[
{ label: 'Default', value: 'option1' },
{ label: 'Comfortable', value: 'option2' },
{ label: 'Compact', value: 'option3' },
]}
value={value}
onValueChange={setValue}
/>
);
}
Horizontal Layout
import { RadioGroup } from '@/components/ui/radio';
import React, { useState } from 'react';
export function RadioHorizontal() {
const [value, setValue] = useState('small');
return (
<RadioGroup
orientation='horizontal'
options={[
{ label: 'Small', value: 'small' },
{ label: 'Medium', value: 'medium' },
{ label: 'Large', value: 'large' },
]}
value={value}
onValueChange={setValue}
/>
);
}
Disabled Options
import { RadioGroup } from '@/components/ui/radio';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function RadioDisabled() {
const [value1, setValue1] = useState('option1');
const [value2, setValue2] = useState('option2');
return (
<View style={{ gap: 24 }}>
{/* Some disabled options */}
<View>
<Text style={{ marginBottom: 12, fontWeight: '500' }}>
With disabled options
</Text>
<RadioGroup
options={[
{ label: 'Available', value: 'option1' },
{ label: 'Disabled', value: 'option2', disabled: true },
{ label: 'Available', value: 'option3' },
{ label: 'Disabled', value: 'option4', disabled: true },
]}
value={value1}
onValueChange={setValue1}
/>
</View>
{/* Entire group disabled */}
<View>
<Text style={{ marginBottom: 12, fontWeight: '500' }}>
Entire group disabled
</Text>
<RadioGroup
disabled
options={[
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
{ label: 'Option 3', value: 'option3' },
]}
value={value2}
onValueChange={setValue2}
/>
</View>
</View>
);
}
Custom Styling
import { RadioGroup } from '@/components/ui/radio';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import React, { useState } from 'react';
export function RadioStyled() {
const green = useThemeColor({}, 'green');
const card = useThemeColor({}, 'card');
const [value1, setValue1] = useState('red');
const [value2, setValue2] = useState('plan1');
return (
<View style={{ gap: 24 }}>
{/* Custom colors */}
<View>
<Text style={{ marginBottom: 12, fontWeight: '500' }}>
Card-like options
</Text>
<RadioGroup
options={[
{ label: 'Red Theme', value: 'red' },
{ label: 'Blue Theme', value: 'blue' },
{ label: 'Green Theme', value: 'green' },
]}
value={value1}
onValueChange={setValue1}
optionStyle={{
paddingVertical: 12,
paddingHorizontal: 12,
backgroundColor: card,
borderRadius: 8,
marginBottom: 4,
}}
labelStyle={{
fontSize: 16,
fontWeight: '500',
}}
/>
</View>
{/* Card-like styling */}
<View>
<Text style={{ marginBottom: 12, fontWeight: '500' }}>
Custom styling
</Text>
<RadioGroup
options={[
{ label: 'Basic Plan - $9/month', value: 'plan1' },
{ label: 'Pro Plan - $19/month', value: 'plan2' },
{ label: 'Enterprise - $49/month', value: 'plan3' },
]}
value={value2}
onValueChange={setValue2}
optionStyle={{
paddingVertical: 16,
paddingHorizontal: 16,
backgroundColor: green,
borderRadius: 12,
marginBottom: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 1,
}}
labelStyle={{
fontSize: 15,
fontWeight: '500',
color: '#1f2937',
}}
/>
</View>
</View>
);
}
Form Integration
import { Button } from '@/components/ui/button';
import { RadioGroup } from '@/components/ui/radio';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
import { Alert } from 'react-native';
export function RadioForm() {
const [experience, setExperience] = useState('');
const [notification, setNotification] = useState('email');
const [theme, setTheme] = useState('system');
const handleSubmit = () => {
if (!experience) {
Alert.alert('Error', 'Please select your experience level');
return;
}
Alert.alert(
'Form Submitted',
`Experience: ${experience}\nNotifications: ${notification}\nTheme: ${theme}`
);
};
return (
<View style={{ paddingVertical: 16, gap: 24 }}>
<Text style={{ fontSize: 18, fontWeight: '600' }}>User Preferences</Text>
<View>
<Text style={{ marginBottom: 12, fontWeight: '500', fontSize: 16 }}>
Experience Level *
</Text>
<RadioGroup
options={[
{ label: 'Beginner', value: 'beginner' },
{ label: 'Intermediate', value: 'intermediate' },
{ label: 'Advanced', value: 'advanced' },
{ label: 'Expert', value: 'expert' },
]}
value={experience}
onValueChange={setExperience}
/>
</View>
<View>
<Text style={{ marginBottom: 12, fontWeight: '500', fontSize: 16 }}>
Notification Preference
</Text>
<RadioGroup
options={[
{ label: 'Email notifications', value: 'email' },
{ label: 'Push notifications', value: 'push' },
{ label: 'SMS notifications', value: 'sms' },
{ label: 'No notifications', value: 'none' },
]}
value={notification}
onValueChange={setNotification}
/>
</View>
<View>
<Text style={{ marginBottom: 12, fontWeight: '500', fontSize: 16 }}>
Theme Preference
</Text>
<RadioGroup
orientation='horizontal'
options={[
{ label: 'Light', value: 'light' },
{ label: 'Dark', value: 'dark' },
{ label: 'System', value: 'system' },
]}
value={theme}
onValueChange={setTheme}
/>
</View>
<Button onPress={handleSubmit} style={{ marginTop: 8 }}>
Save Preferences
</Button>
</View>
);
}
Large Size
import { RadioGroup } from '@/components/ui/radio';
import React, { useState } from 'react';
export function RadioLarge() {
const [value, setValue] = useState('option1');
return (
<RadioGroup
options={[
{ label: 'Large Option One', value: 'option1' },
{ label: 'Large Option Two', value: 'option2' },
{ label: 'Large Option Three', value: 'option3' },
]}
value={value}
onValueChange={setValue}
style={{ gap: 12 }}
optionStyle={{
paddingVertical: 12,
}}
labelStyle={{
fontSize: 18,
fontWeight: '500',
lineHeight: 28,
}}
/>
);
}
Single Radio Button
import { RadioButton } from '@/components/ui/radio';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function RadioSingle() {
const [selectedValue, setSelectedValue] = useState('option2');
const options = [
{ label: 'First Option', value: 'option1' },
{ label: 'Second Option', value: 'option2' },
{ label: 'Third Option', value: 'option3' },
{ label: 'Disabled Option', value: 'option4', disabled: true },
];
return (
<View style={{ gap: 16 }}>
<Text style={{ fontWeight: '500', fontSize: 16 }}>
Individual Radio Buttons
</Text>
<View style={{ gap: 8 }}>
{options.map((option) => (
<RadioButton
key={option.value}
option={option}
selected={selectedValue === option.value}
onPress={() => setSelectedValue(option.value)}
/>
))}
</View>
<Text variant='caption'>Selected: {selectedValue}</Text>
</View>
);
}
API Reference
RadioGroup
The main container component that manages a group of radio buttons.
Prop | Type | Default | Description |
---|---|---|---|
options | RadioOption[] | - | Array of radio button options. |
value | string | - | The currently selected value. |
onValueChange | (value: string) => void | - | Callback fired when the selection changes. |
disabled | boolean | false | Whether the entire group is disabled. |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout orientation of the radio buttons. |
style | ViewStyle | - | Additional styles for the group container. |
optionStyle | ViewStyle | - | Additional styles for each radio button. |
labelStyle | TextStyle | - | Additional styles for radio button labels. |
RadioButton
Individual radio button component for custom layouts.
Prop | Type | Default | Description |
---|---|---|---|
option | RadioOption | - | The radio option data. |
selected | boolean | - | Whether this radio button is selected. |
onPress | () => void | - | Callback fired when the button is pressed. |
disabled | boolean | false | Whether this radio button is disabled. |
style | ViewStyle | - | Additional styles for the button container. |
labelStyle | TextStyle | - | Additional styles for the button label. |
RadioOption
The shape of each radio option object.
Property | Type | Description |
---|---|---|
label | string | The display text for the radio button. |
value | string | The value associated with this option. |
disabled | boolean | Whether this specific option is disabled. |
Accessibility
The Radio component is built with accessibility in mind:
- Uses TouchableOpacity for proper touch feedback
- Supports disabled states with appropriate visual feedback
- Proper opacity changes for disabled options
- Screen reader friendly with semantic structure
- Supports keyboard navigation patterns
- Clear visual indicators for selected state