Skip to content

Select ​

A Base UI select in the style of a menu, so a settings field and a picker in a toolbar read the same. It brings the keyboard with it: arrows, Home and End, typeahead, Enter and Escape.

tsx
import { Select } from '@basmilius/react-ui';
tsx
import { useState } from 'react';
import { Select } from '@basmilius/react-ui';

type Theme = 'system' | 'light' | 'dark';

export default function SelectDemo() {
    const [theme, setTheme] = useState<Theme>('system');
    const [sort, setSort] = useState<string | null>(null);

    return (
        <div className="flex flex-wrap items-center gap-3">
            <Select<Theme>
                label="Theme"
                value={theme}
                onValueChange={setTheme}
                items={[
                    { value: 'system', label: 'Match the system' },
                    { value: 'light', label: 'Light' },
                    { value: 'dark', label: 'Dark' }
                ]}
            />
            <Select
                label="Sort by"
                placeholder="Sort by"
                variant="ghost"
                size="sm"
                value={sort}
                onValueChange={setSort}
                items={[
                    { value: 'name', label: 'Name' },
                    { value: 'modified', label: 'Last modified', description: 'The newest change first' },
                    { value: 'size', label: 'Size', disabled: true }
                ]}
            />
        </div>
    );
}

outlined is the default, a bordered field. ghost is the quiet trigger of a toolbar. An item can carry an icon, a description on a second line, and disabled. With no value picked the trigger shows the placeholder, or the library's "Select".

Groups ​

Hand items a list of groups instead of a list of items, and each group gets a label above its rows.

tsx
import { useState } from 'react';
import { Select } from '@basmilius/react-ui';

export default function SelectGroups() {
    const [font, setFont] = useState<string | null>('jetbrains');

    return (
        <Select
            label="Font"
            value={font}
            onValueChange={setFont}
            items={[
                {
                    label: 'Monospace',
                    items: [
                        { value: 'jetbrains', label: 'JetBrains Mono' },
                        { value: 'sf-mono', label: 'SF Mono' }
                    ]
                },
                {
                    label: 'Proportional',
                    items: [
                        { value: 'inter', label: 'Inter' },
                        { value: 'system', label: 'System font' }
                    ]
                }
            ]}
        />
    );
}

Props ​

Select is generic over the value, a string type.

PropTypeDefault
valueT | nullRequired.
onValueChange(value: T) => voidRequired.
itemsSelectItem<T>[] | SelectGroup<T>[]Required.
labelstringRequired. The accessible name of the trigger; the row above it usually carries the visible one.
placeholderstring'Select'
size'sm' | 'md''md'
variant'outlined' | 'ghost''outlined'
disabledboolean
align'start' | 'end''start'Where the popup lines up with the trigger.
truncateValuebooleantrueCuts a long value off with an ellipsis.
classNamestring
refRef<HTMLButtonElement>The trigger.

A SelectItem<T> is { value, label, description?, icon?, disabled? }. A SelectGroup<T> is { label, items }. SelectProps, SelectItem and SelectGroup are exported types.