Radio

Radio buttons allow the user to select one option from a set. Use RadioGroup for a complete set with validation support.

Basic RadioGroup

Radio group with label and options

await import('/components/data-input/radio.js');
const { tags, $ } = Lightview;
const { div, RadioGroup } = tags;

// 1. Basic radio group
const basic = RadioGroup({
    label: 'Favorite Color',
    name: 'color',
    options: ['Red', 'Blue', 'Green', 'Yellow'],
    color: 'primary'
});

// 2. With descriptions
const withDesc = RadioGroup({
    label: 'Subscription Plan',
    name: 'plan',
    options: [
        { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
        { value: 'pro', label: 'Pro', description: '$9/month, all features' },
        { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
    ],
    color: 'secondary'
});

// 3. Horizontal layout
const horizontal = RadioGroup({
    label: 'Size',
    name: 'size',
    options: ['S', 'M', 'L', 'XL'],
    horizontal: true,
    color: 'accent'
});

// Insert all examples
$('#example').content(
    div({ style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;' }, basic, withDesc, horizontal)
);
await import('/components/data-input/radio.js');
const { $, tags } = Lightview;
const { RadioGroup, div } = tags;

const basic = {
    tag: RadioGroup,
    attributes: {
        label: 'Favorite Color',
        name: 'color',
        options: ['Red', 'Blue', 'Green', 'Yellow'],
        color: 'primary'
    }
};

const withDesc = {
    tag: RadioGroup,
    attributes: {
        label: 'Subscription Plan',
        name: 'plan',
        options: [
            { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
            { value: 'pro', label: 'Pro', description: '$9/month, all features' },
            { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
        ],
        color: 'secondary'
    }
};

const horizontal = {
    tag: RadioGroup,
    attributes: {
        label: 'Size',
        name: 'size',
        options: ['S', 'M', 'L', 'XL'],
        horizontal: true,
        color: 'accent'
    }
};

$('#example').content({
    tag: div,
    attributes: { style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;' },
    children: [basic, withDesc, horizontal]
});
await import('/components/data-input/radio.js');
const { $ } = Lightview;

$('#example').content({
    div: {
        style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;',
        children: [
            {
                RadioGroup: {
                    label: 'Favorite Color',
                    name: 'color',
                    options: ['Red', 'Blue', 'Green', 'Yellow'],
                    color: 'primary'
                }
            },
            {
                RadioGroup: {
                    label: 'Subscription Plan',
                    name: 'plan',
                    options: [
                        { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
                        { value: 'pro', label: 'Pro', description: '$9/month, all features' },
                        { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
                    ],
                    color: 'secondary'
                }
            },
            {
                RadioGroup: {
                    label: 'Size',
                    name: 'size',
                    options: ['S', 'M', 'L', 'XL'],
                    horizontal: true,
                    color: 'accent'
                }
            }
        ]
    }
});

<div style="display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;">
    <lv-radio-group 
        label="Favorite Color" 
        name="color-html" 
        options='["Red", "Blue", "Green", "Yellow"]'
        color="primary">
    </lv-radio-group>

    <lv-radio-group 
        label="Subscription Plan" 
        name="plan-html" 
        options='[{"value":"free","label":"Free","description":"Basic features, limited usage"},{"value":"pro","label":"Pro","description":"$9/month, all features"},{"value":"enterprise","label":"Enterprise","description":"Custom pricing, priority support"}]'
        color="secondary">
    </lv-radio-group>

    <lv-radio-group 
        label="Size" 
        name="size-html" 
        options='["S", "M", "L", "XL"]'
        horizontal
        color="accent">
    </lv-radio-group>
</div>

Reactive Example

Two-way binding with signals and validation

await import('/components/data-input/radio.js');
const { signal, tags, $ } = Lightview;
const { div, p, span, RadioGroup } = tags;

// Signal for selected value
const selectedPriority = signal('');

// Priority descriptions
const priorityInfo = {
    low: { emoji: '🟢', text: 'Can wait, no rush' },
    medium: { emoji: '🟡', text: 'Should be addressed soon' },
    high: { emoji: '🟠', text: 'Needs attention today' },
    critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
};

// Reactive radio group
const reactiveDemo = div({ style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
    RadioGroup({
        label: 'Issue Priority',
        name: 'priority',
        value: selectedPriority,
        options: [
            { value: 'low', label: 'Low' },
            { value: 'medium', label: 'Medium' },
            { value: 'high', label: 'High' },
            { value: 'critical', label: 'Critical' }
        ],
        required: true,
        color: 'primary'
    }),
    p({ style: 'font-size: 1.125rem;' },
        () => {
            const priority = selectedPriority.value;
            if (!priority) return span({ style: 'opacity: 0.5;' }, 'Select a priority level');
            const info = priorityInfo[priority];
            return span({}, info.emoji, ' ', info.text);
        }
    )
);

$('#example').content(reactiveDemo);
await import('/components/data-input/radio.js');
const { signal, $, tags } = Lightview;
const { RadioGroup, div, p, span } = tags;

const selectedPriority = signal('');

const priorityInfo = {
    low: { emoji: '🟢', text: 'Can wait, no rush' },
    medium: { emoji: '🟡', text: 'Should be addressed soon' },
    high: { emoji: '🟠', text: 'Needs attention today' },
    critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
};

const reactiveDemo = {
    tag: div,
    attributes: { style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
    children: [
        {
            tag: RadioGroup,
            attributes: {
                label: 'Issue Priority',
                name: 'priority',
                value: selectedPriority,
                options: [
                    { value: 'low', label: 'Low' },
                    { value: 'medium', label: 'Medium' },
                    { value: 'high', label: 'High' },
                    { value: 'critical', label: 'Critical' }
                ],
                required: true,
                color: 'primary'
            }
        },
        {
            tag: p,
            attributes: { style: 'font-size: 1.125rem;' },
            children: [
                () => {
                    const priority = selectedPriority.value;
                    if (!priority) return { tag: span, attributes: { style: 'opacity: 0.5;' }, children: ['Select a priority level'] };
                    const info = priorityInfo[priority];
                    return { tag: span, children: [info.emoji, ' ', info.text] };
                }
            ]
        }
    ]
};

$('#example').content(reactiveDemo);
await import('/components/data-input/radio.js');
const { signal, $ } = Lightview;

const selectedPriority = signal('');

const priorityInfo = {
    low: { emoji: '🟢', text: 'Can wait, no rush' },
    medium: { emoji: '🟡', text: 'Should be addressed soon' },
    high: { emoji: '🟠', text: 'Needs attention today' },
    critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
};

const reactiveDemo = {
    div: {
        style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;',
        children: [
            {
                RadioGroup: {
                    label: 'Issue Priority',
                    name: 'priority',
                    value: selectedPriority,
                    options: [
                        { value: 'low', label: 'Low' },
                        { value: 'medium', label: 'Medium' },
                        { value: 'high', label: 'High' },
                        { value: 'critical', label: 'Critical' }
                    ],
                    required: true,
                    color: 'primary'
                }
            },
            {
                p: {
                    style: 'font-size: 1.125rem;',
                    children: [
                        () => {
                            const priority = selectedPriority.value;
                            if (!priority) return { span: { style: 'opacity: 0.5;', children: ['Select a priority level'] } };
                            const info = priorityInfo[priority];
                            return { span: { children: [info.emoji, ' ', info.text] } };
                        }
                    ]
                }
            }
        ]
    }
};

$('#example').content(reactiveDemo);

RadioGroup Props

Prop Type Default Description
options array [] Array of strings or objects {value, label, description, disabled}
value * | signal - Selected value (reactive with signals)
defaultValue * null Default value for uncontrolled mode
name string auto Radio group name for form submission
label string - Group label displayed above options
helper string - Helper text displayed below options
error string | function - Error message or reactive error function
validate function - Validation function: (value) => errorMessage | null
color string - 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'
size string 'md' 'xs' | 'sm' | 'md' | 'lg'
horizontal boolean false Arrange options horizontally
disabled boolean false Disable all options
required boolean false Mark as required field
onChange function - Callback when value changes: (value) => void
useShadow boolean * Render in Shadow DOM

Radio Gallery

Live examples using <lv-radio> and <lv-radio-group> custom elements.

Colors

Sizes

Radio Groups