Select

Select allows the user to pick a value from a list of options. Supports labels, validation, helper text, and reactive state binding.

Basic Examples

Simple selects with various configurations

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

// 1. Basic select with string options
const basic = Select({ 
    placeholder: 'Pick a movie franchise',
    options: ['Star Wars', 'Harry Potter', 'Lord of the Rings', 'Marvel']
});

// 2. Select with label and helper
const withLabel = Select({ 
    label: 'Country',
    placeholder: 'Select your country',
    options: [
        { value: 'us', label: 'United States' },
        { value: 'uk', label: 'United Kingdom' },
        { value: 'ca', label: 'Canada' },
        { value: 'au', label: 'Australia' }
    ],
    helper: 'We use this for shipping calculations'
});

// 3. Required select with color
const required = Select({ 
    label: 'Priority',
    placeholder: 'Select priority...',
    options: ['Low', 'Medium', 'High', 'Critical'],
    color: 'primary',
    required: true
});

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

const basic = {
    tag: Select,
    attributes: { 
        placeholder: 'Pick a movie franchise',
        options: ['Star Wars', 'Harry Potter', 'Lord of the Rings', 'Marvel']
    }
};

const withLabel = {
    tag: Select,
    attributes: { 
        label: 'Country',
        placeholder: 'Select your country',
        options: [
            { value: 'us', label: 'United States' },
            { value: 'uk', label: 'United Kingdom' },
            { value: 'ca', label: 'Canada' },
            { value: 'au', label: 'Australia' }
        ],
        helper: 'We use this for shipping calculations'
    }
};

const required = {
    tag: Select,
    attributes: { 
        label: 'Priority',
        placeholder: 'Select priority...',
        options: ['Low', 'Medium', 'High', 'Critical'],
        color: 'primary',
        required: true
    }
};

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

const demo = {
    div: {
        style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;',
        children: [
            { 
                Select: { 
                    placeholder: 'Pick a movie franchise',
                    options: ['Star Wars', 'Harry Potter', 'Lord of the Rings', 'Marvel']
                } 
            },
            { 
                Select: { 
                    label: 'Country',
                    placeholder: 'Select your country',
                    options: [
                        { value: 'us', label: 'United States' },
                        { value: 'uk', label: 'United Kingdom' },
                        { value: 'ca', label: 'Canada' },
                        { value: 'au', label: 'Australia' }
                    ],
                    helper: 'We use this for shipping calculations'
                } 
            },
            { 
                Select: { 
                    label: 'Priority',
                    placeholder: 'Select priority...',
                    options: ['Low', 'Medium', 'High', 'Critical'],
                    color: 'primary',
                    required: true
                } 
            }
        ]
    }
};

$('#example').content(demo);
<!-- Import the component (registers lv-select) -->
<script type="module" src="/components/data-input/select.js"></script>

<div style="display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;">
    <lv-select 
        placeholder="Pick a movie franchise" 
        options='["Star Wars", "Harry Potter", "Lord of the Rings", "Marvel"]'>
    </lv-select>
    
    <lv-select 
        label="Country" 
        placeholder="Select your country"
        options='[{"value":"us","label":"United States"},{"value":"uk","label":"United Kingdom"}]'
        helper="We'll never share your data.">
    </lv-select>
    
    <lv-select 
        label="Priority" 
        placeholder="Select priority..." 
        options='["Low", "Medium", "High", "Critical"]'
        color="primary"
        required>
    </lv-select>
</div>

Reactive Example

Two-way binding with signals and live validation

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

// Signal for two-way binding
const selectedRole = signal('');

// Validation function
const validateRole = (val) => {
    if (!val) return 'Please select a role';
    return null;
};

// Role descriptions
const roleDescriptions = {
    admin: 'Full access to all features',
    editor: 'Can edit and publish content',
    viewer: 'Read-only access',
    guest: 'Limited access to public content'
};

// Reactive select with validation
const reactiveDemo = div({ style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
    Select({ 
        label: 'User Role',
        placeholder: 'Assign a role...',
        value: selectedRole,
        options: [
            { value: 'admin', label: 'Administrator' },
            { value: 'editor', label: 'Editor' },
            { value: 'viewer', label: 'Viewer' },
            { value: 'guest', label: 'Guest' }
        ],
        validate: validateRole,
        required: true
    }),
    p({ style: 'font-size: 0.875rem;' }, 
        () => {
            const role = selectedRole.value;
            if (!role) return span({ style: 'opacity: 0.7;' }, 'Select a role to see its description');
            return span({ style: 'color: oklch(var(--p));' }, roleDescriptions[role]);
        }
    )
);

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

const selectedRole = signal('');

const validateRole = (val) => {
    if (!val) return 'Please select a role';
    return null;
};

const roleDescriptions = {
    admin: 'Full access to all features',
    editor: 'Can edit and publish content',
    viewer: 'Read-only access',
    guest: 'Limited access to public content'
};

const reactiveDemo = {
    tag: div,
    attributes: { style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
    children: [
        {
            tag: Select,
            attributes: {
                label: 'User Role',
                placeholder: 'Assign a role...',
                value: selectedRole,
                options: [
                    { value: 'admin', label: 'Administrator' },
                    { value: 'editor', label: 'Editor' },
                    { value: 'viewer', label: 'Viewer' },
                    { value: 'guest', label: 'Guest' }
                ],
                validate: validateRole,
                required: true
            }
        },
        {
            tag: p,
            attributes: { style: 'font-size: 0.875rem;' },
            children: [
                () => {
                    const role = selectedRole.value;
                    if (!role) return { tag: span, attributes: { style: 'opacity: 0.7;' }, children: ['Select a role to see its description'] };
                    return { tag: span, attributes: { style: 'color: oklch(var(--p));' }, children: [roleDescriptions[role]] };
                }
            ]
        }
    ]
};

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

const selectedRole = signal('');

const validateRole = (val) => {
    if (!val) return 'Please select a role';
    return null;
};

const roleDescriptions = {
    admin: 'Full access to all features',
    editor: 'Can edit and publish content',
    viewer: 'Read-only access',
    guest: 'Limited access to public content'
};

const reactiveDemo = {
    div: {
        style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;',
        children: [
            {
                Select: {
                    label: 'User Role',
                    placeholder: 'Assign a role...',
                    value: selectedRole,
                    options: [
                        { value: 'admin', label: 'Administrator' },
                        { value: 'editor', label: 'Editor' },
                        { value: 'viewer', label: 'Viewer' },
                        { value: 'guest', label: 'Guest' }
                    ],
                    validate: validateRole,
                    required: true
                }
            },
            {
                p: {
                    style: 'font-size: 0.875rem;',
                    children: [
                        () => {
                            const role = selectedRole.value;
                            if (!role) return { span: { style: 'opacity: 0.7;', children: ['Select a role to see its description'] } };
                            return { span: { style: 'color: oklch(var(--p));', children: [roleDescriptions[role]] } };
                        }
                    ]
                }
            }
        ]
    }
};

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

Props

Prop Type Default Description
options array [] Array of strings or objects {value, label, disabled}
value * | signal - Selected value (reactive with signals)
defaultValue * '' Default value for uncontrolled mode
placeholder string - Placeholder option (disabled first option)
label string - Label text displayed above select
helper string - Helper text displayed below the select
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'
ghost boolean false Ghost style (no background)
disabled boolean false Disable the select
required boolean false Mark as required field (shows asterisk)
onChange function - Callback when value changes: (value, event) => void
useShadow boolean * Render in Shadow DOM. *Follows global initComponents() setting

Select Gallery

Live examples using <lv-select> custom elements.

Sizes

Colors

Labels & Assistance

States