Radio
Import
Section titled “Import”import { Radio, RadioGroup } from '@delightstack/components';The RadioGroup is re-exported from the same module. The context type is also available:
import type { RadioGroupContext } from '@delightstack/components';Basic Usage
Section titled “Basic Usage”<script> import { Radio, RadioGroup } from '@delightstack/components';
let selectedSize = $state('medium');</script>
<RadioGroup bind:value={selectedSize} name="size" label="Size"> <Radio value="small" label="Small" /> <Radio value="medium" label="Medium" /> <Radio value="large" label="Large" /></RadioGroup>Examples
Section titled “Examples”Vertical Group (Default)
Section titled “Vertical Group (Default)”Size
Small
Medium
Large
View code
<RadioGroup name="size" label="Size"> <Radio value="small" label="Small" /> <Radio value="medium" label="Medium" /> <Radio value="large" label="Large" /></RadioGroup>Horizontal Layout
Section titled “Horizontal Layout”Preference
Yes
No
Maybe
View code
<RadioGroup horizontal name="preference" label="Preference"> <Radio value="yes" label="Yes" /> <Radio value="no" label="No" /> <Radio value="maybe" label="Maybe" /></RadioGroup>With Descriptions
Section titled “With Descriptions”Select a plan
Free Basic features, forever free
Pro Advanced features, $10/mo
Enterprise Custom pricing
View code
<RadioGroup name="plan" label="Select a plan"> <Radio value="free" label="Free" description="Basic features, forever free" /> <Radio value="pro" label="Pro" description="Advanced features, $10/mo" /> <Radio value="enterprise" label="Enterprise" description="Custom pricing" /></RadioGroup>With Error
Section titled “With Error”Agreement Please select an option
I agree
I disagree
View code
<script> import { Radio, RadioGroup } from '@delightstack/components';
let agreement = $state('');</script>
<RadioGroup bind:value={agreement} required error={!agreement ? 'Please select an option' : ''} name="agreement" label="Agreement"> <Radio value="agree" label="I agree" /> <Radio value="disagree" label="I disagree" /></RadioGroup>Standalone Radio
Section titled “Standalone Radio”A Radio can be used without a RadioGroup by managing checked directly.
Option 1
Option 2
Selected: option1
View code
<script> import { Radio } from '@delightstack/components';
let selected = $state('option1');</script>
<Radio value="option1" checked={selected === 'option1'} onchange={() => selected = 'option1'} label="Option 1"/><Radio value="option2" checked={selected === 'option2'} onchange={() => selected = 'option2'} label="Option 2"/>Small (size 0)
Option A
Option B
Default (size 1)
Option A
Option B
Medium (size 2)
Option A
Option B
Large (size 3)
Option A
Option B
View code
<RadioGroup bind:value={val0} name="size0" size="0" label="Small (size 0)"> <Radio value="a" label="Option A" /> <Radio value="b" label="Option B" /></RadioGroup>
<RadioGroup bind:value={val1} name="size1" size="1" label="Default (size 1)"> <Radio value="a" label="Option A" /> <Radio value="b" label="Option B" /></RadioGroup>
<RadioGroup bind:value={val2} name="size2" size="2" label="Medium (size 2)"> <Radio value="a" label="Option A" /> <Radio value="b" label="Option B" /></RadioGroup>
<RadioGroup bind:value={val3} name="size3" size="3" label="Large (size 3)"> <Radio value="a" label="Option A" /> <Radio value="b" label="Option B" /></RadioGroup>| Prop | Type | Default | Description |
|---|---|---|---|
value | string | '' | Option value (bindable) |
checked | boolean | false | Selected state, bindable (for standalone use) |
disabled | boolean | false | Disable this option |
size | '0' | '1' | '2' | '3' | '1' | Radio size |
label | string | '' | Label text |
description | string | '' | Helper text below label |
tooltip | string | '' | Tooltip text on hover |
dense | boolean | false | Tighter label/circle spacing |
comfortable | boolean | false | More label/circle spacing |
id | string | auto | Element ID |
name | string | '' | Form field name |
class | string | '' | Additional CSS classes |
RadioGroup
Section titled “RadioGroup”| Prop | Type | Default | Description |
|---|---|---|---|
value | string | '' | Selected value, bindable |
name | string | '' | Shared group name |
disabled | boolean | false | Disable all radio options |
size | '0' | '1' | '2' | '3' | '1' | Size for all child radios |
horizontal | boolean | false | Horizontal layout |
label | string | '' | Group label |
error | string | '' | Group-level error message |
required | boolean | false | Selection is required |
dense | boolean | false | Compact spacing between options |
comfortable | boolean | false | Relaxed spacing between options |
id | string | auto | Element ID |
class | string | '' | Additional CSS classes |
children | Snippet | - | Radio children |
Events
Section titled “Events”| Event | Detail | Description |
|---|---|---|
onchange | { value: string } | Selection changed |
RadioGroup
Section titled “RadioGroup”| Event | Detail | Description |
|---|---|---|
onchange | { value: string } | Selection changed |
interface RadioGroupContext { name: string; value: string; disabled: boolean; size: '0' | '1' | '2' | '3'; select: (value: string) => void;}Accessibility
Section titled “Accessibility”- Hidden native
<input type="radio">for form submission and semantics aria-checkedreflects selection statearia-describedbyfor description textaria-requiredwhen required- RadioGroup rendered as
<div role="radiogroup">witharia-labelledby - Full keyboard navigation: Arrow keys move between options within a group, Tab moves between groups
- Focus ring visible only on keyboard focus (
:focus-visible) - Selection dot animates with
scale()for satisfying visual feedback