Interactive demo of button radio field
Overview
The button radio field presents radio options as a segmented button group. It’s ideal when you have 2-5 options and want a more compact, visually prominent selection UI.
Usage
Basic Button Radio
import { FormBuilder } from '@saastro/forms';
const config = FormBuilder.create('form')
.addField('size', (f) =>
f
.type('button-radio')
.label('Size')
.options([
{ label: 'S', value: 'small' },
{ label: 'M', value: 'medium' },
{ label: 'L', value: 'large' },
{ label: 'XL', value: 'xlarge' },
])
.value('medium')
.required(),
)
.addStep('main', ['size'])
.build();
Binary Choice
.addField('billingCycle', (f) =>
f.type('button-radio')
.label('Billing')
.options([
{ label: 'Monthly', value: 'monthly' },
{ label: 'Yearly', value: 'yearly' },
])
.value('monthly')
.required()
)
With Icons (via label)
.addField('view', (f) =>
f.type('button-radio')
.label('View')
.options([
{ label: '📋 List', value: 'list' },
{ label: '📊 Grid', value: 'grid' },
{ label: '📈 Chart', value: 'chart' },
])
.value('list')
.required()
)
JSON Configuration
{
"type": "button-radio",
"label": "Size",
"options": [
{ "label": "S", "value": "small" },
{ "label": "M", "value": "medium" },
{ "label": "L", "value": "large" }
],
"value": "medium",
"schema": { "required": true }
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'button-radio' | - | Field type (required) |
label | string | - | Group label |
helperText | string | - | Help text below field |
options | Option[] | - | Array of button options |
value | string | - | Default selected value |
optionsClassName | string | - | CSS classes for buttons container |
columns | Partial<Record<Breakpoint, number>> | - | Grid columns by breakpoint |
disabled | boolean | function | ConditionGroup | false | Disable all buttons |
hidden | boolean | function | ConditionGroup | Responsive | false | Hide the field |
Button Radio vs Radio
| Use Button Radio | Use Radio |
|---|---|
| 2-5 options | Any number |
| Compact UI | Detailed options |
| Visual selection | Description needed |
| Horizontal layout | Vertical layout |
Validation
Required Selection
.addField('priority', (f) =>
f.type('button-radio')
.label('Priority')
.options([
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
])
.required('Please select a priority')
)
Styling
Custom Classes
.addField('size', (f) =>
f.type('button-radio')
.label('Size')
.options([...])
.required()
.classNames({
wrapper: 'bg-muted/30 p-4 rounded-lg',
label: 'text-lg font-semibold mb-3',
error: 'text-destructive text-sm',
})
)
Options Layout with optionsClassName
Control button arrangement:
{
"type": "button-radio",
"label": "Size",
"optionsClassName": "flex flex-wrap gap-2",
"options": [...]
}
Responsive Layout
.addField('billing', (f) =>
f.type('button-radio')
.label('Billing')
.options([...])
.columns({ default: 12, md: 6 })
)
JSON Styling
{
"type": "button-radio",
"label": "Size",
"wrapper_className": "bg-muted/30 p-4 rounded-lg",
"label_className": "text-lg font-semibold",
"optionsClassName": "inline-flex gap-1",
"columns": { "default": 12, "md": 6 }
}
Related Fields
- Radio - Traditional radio group
- Button Checkbox - Multi-select buttons
- Select - Dropdown selection
Accessibility
- Uses Radix UI ToggleGroup (single mode)
- Keyboard navigation (Arrow keys)
- Proper ARIA roles
- Focus visible states