Interactive demo of radio group field
/**
* Radio Field Demo - Interactive examples of radio group fields
*/
import { Form, FormBuilder } from '@saastro/forms';
import { FormProvider } from '@/components/FormProvider';
import { TooltipProvider } from '@/components/ui/tooltip';
const config = FormBuilder.create('radio-demo')
.layout('manual')
.columns(12)
.addField('plan', (f) =>
f
.type('radio')
.label('Select a plan')
.helperText('Choose the plan that fits your needs')
.options([
{ label: 'Free', value: 'free' },
{ label: 'Pro', value: 'pro' },
{ label: 'Enterprise', value: 'enterprise' },
])
.value('pro')
.required('Please select a plan')
.columns({ default: 12, md: 6 }),
)
.addField('frequency', (f) =>
f
.type('radio')
.label('Billing frequency')
.options([
{ label: 'Monthly', value: 'monthly' },
{ label: 'Yearly (save 20%)', value: 'yearly' },
])
.required()
.columns({ default: 12, md: 6 }),
)
.addField('shipping', (f) =>
f
.type('radio')
.label('Shipping method')
.helperText('Select delivery speed')
.options([
{ label: 'Standard (5-7 days)', value: 'standard' },
{ label: 'Express (2-3 days)', value: 'express' },
{ label: 'Overnight', value: 'overnight' },
])
.required()
.columns({ default: 12 }),
)
.addStep('main', ['plan', 'frequency', 'shipping'])
.build();
export default function RadioDemo() {
const handleSubmit = (data: Record<string, unknown>) => {
console.log('Form submitted:', data);
alert('Form submitted! Check console for data.');
};
return (
<TooltipProvider>
<FormProvider>
<Form config={config} onSubmit={handleSubmit} className="space-y-4" />
</FormProvider>
</TooltipProvider>
);
} Overview
The radio group field allows users to select exactly one option from a list. Use it when users need to see all options at once and make a single selection.
Usage
Basic Radio Group
import { FormBuilder } from '@saastro/forms';
const config = FormBuilder.create('survey')
.addField('satisfaction', (f) =>
f
.type('radio')
.label('How satisfied are you?')
.options([
{ label: 'Very satisfied', value: 'very-satisfied' },
{ label: 'Satisfied', value: 'satisfied' },
{ label: 'Neutral', value: 'neutral' },
{ label: 'Dissatisfied', value: 'dissatisfied' },
])
.required('Please select an option'),
)
.addStep('main', ['satisfaction'])
.build();
With Default Value
.addField('plan', (f) =>
f.type('radio')
.label('Select a plan')
.options([
{ label: 'Free', value: 'free' },
{ label: 'Pro', value: 'pro' },
{ label: 'Enterprise', value: 'enterprise' },
])
.value('pro')
.required()
)
With Descriptions
.addField('shipping', (f) =>
f.type('radio')
.label('Shipping method')
.options([
{ label: 'Standard', value: 'standard', description: '5-7 business days' },
{ label: 'Express', value: 'express', description: '2-3 business days' },
{ label: 'Overnight', value: 'overnight', description: 'Next business day' },
])
.required()
)
JSON Configuration
{
"type": "radio",
"label": "Select a plan",
"options": [
{ "label": "Free", "value": "free" },
{ "label": "Pro", "value": "pro" },
{ "label": "Enterprise", "value": "enterprise" }
],
"value": "pro",
"schema": { "required": true }
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'radio' | - | Field type (required) |
label | string | - | Group label |
options | Option[] | - | Array of options |
value | string | - | Default selected value |
optionsClassName | string | - | CSS classes for options container |
columns | Partial<Record<Breakpoint, number>> | - | Grid columns by breakpoint |
disabled | boolean | function | ConditionGroup | false | Disable all options |
hidden | boolean | function | ConditionGroup | Responsive | false | Hide the field |
Option Object
| Property | Type | Description |
|---|---|---|
label | string | Display text |
value | string | Value when selected |
description | string | Optional description |
disabled | boolean | Disable this option |
Validation
Required Selection
.addField('gender', (f) =>
f.type('radio')
.label('Gender')
.options([
{ label: 'Male', value: 'male' },
{ label: 'Female', value: 'female' },
{ label: 'Other', value: 'other' },
{ label: 'Prefer not to say', value: 'none' },
])
.required('Please select an option')
)
Conditional Logic
Show options based on another field
.addField('paymentMethod', (f) =>
f.type('radio')
.label('Payment method')
.options([
{ label: 'Credit Card', value: 'card' },
{ label: 'PayPal', value: 'paypal' },
{ label: 'Bank Transfer', value: 'bank' },
])
.hidden((values) => values.total === 0)
)
Styling
Custom Classes
.addField('plan', (f) =>
f.type('radio')
.label('Select a plan')
.options([...])
.required()
.classNames({
wrapper: 'bg-muted/30 p-4 rounded-lg',
label: 'text-lg font-semibold',
error: 'text-destructive',
})
)
Options Layout
Control how options are arranged using optionsClassName:
{
"type": "radio",
"label": "Plan",
"optionsClassName": "grid grid-cols-1 md:grid-cols-3 gap-4",
"options": [...]
}
Responsive Layout
.addField('plan', (f) =>
f.type('radio')
.label('Select a plan')
.options([...])
.columns({ default: 12, md: 6 })
)
JSON Styling
{
"type": "radio",
"label": "Plan",
"wrapper_className": "bg-muted/30 p-4 rounded-lg",
"label_className": "text-lg font-semibold",
"optionsClassName": "space-y-3",
"columns": { "default": 12, "md": 6 }
}
Related Fields
- Select - Dropdown for many options
- Button Radio - Radio styled as buttons
- Checkbox Group - Multiple selection
Radio vs Select
| Use Radio | Use Select |
|---|---|
| 2-5 options | 6+ options |
| Options need visibility | Space is limited |
| Options have descriptions | Simple list |
| Important decision | Quick selection |
Accessibility
- Uses Radix UI RadioGroup for accessibility
- Supports keyboard navigation (Arrow keys)
- Proper ARIA roles and labels
- Focus visible states
- Screen reader announcements