# Select

**A common form component for choosing a predefined value in a dropdown menu.**

**Reference:** [View Source](https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Primitives/Select) · [Zag.js Docs](https://zagjs.com/components/react/select)

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'apple', label: 'Apple'},
        1: {value: 'banana', label: 'Banana'},
        2: {value: 'cherry', label: 'Cherry'}
    }"
    as="collection" />

<ui:select.root collection="{collection}">
    <ui:select.label>Select a fruit</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose a fruit" />
    </ui:select.control>
    <ui:select.content>
        <ui:select.list>
            <f:for each="{collection.items}" as="item">
                <ui:select.item item="{item}">
                    <ui:select.itemText>{item.label}</ui:select.itemText>
                    <ui:select.itemIndicator />
                </ui:select.item>
            </f:for>
        </ui:select.list>
    </ui:select.content>
</ui:select.root>
```

## Features

- Support for single and multiple selection
- Typeahead to allow focusing items by typing text
- Keyboard navigation support including arrow keys, home/end
- Supports disabled items and groups
- Can host other widgets, like tabs, next to the list when the popup is a `dialog`
- Works with Field component for form integration
- Supports custom positioning

## Anatomy

Zag puts the listbox semantics, focus, scrolling and the active option on `list`, so the options belong inside `list` rather than directly inside `content`, which is a plain wrapper around it (a dialog, with the `dialog` popup type). The styled `ui:select.content` is the `positioner` and `content` in one part, and `ui:select.list` is the `list` - you place it inside the content yourself:

```html
<ui:select.content>
    <ui:select.list>
        <ui:select.item>...</ui:select.item>
    </ui:select.list>
</ui:select.content>
```

```html
<primitives:select.root>
    <primitives:select.label />
    <primitives:select.control>
        <primitives:select.trigger>
            <primitives:select.valueText />
            <primitives:select.indicator />
        </primitives:select.trigger>
        <primitives:select.clearTrigger />
    </primitives:select.control>
    <primitives:select.positioner>
        <primitives:select.content>
            <primitives:select.list>
                <primitives:select.item>
                    <primitives:select.itemText />
                    <primitives:select.itemIndicator />
                </primitives:select.item>
                <primitives:select.itemGroup>
                    <primitives:select.itemGroupLabel />
                </primitives:select.itemGroup>
            </primitives:select.list>
        </primitives:select.content>
    </primitives:select.positioner>
    <primitives:select.hiddenSelect />
</primitives:select.root>
```

## Installation

```bash
typo3 ui:add select
```

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Registry/Select) into your project.

Read more about installing [Components and Primitives](/docs/core-concepts/primitives.md).

## Examples

### Default Value

Set an initial selected value.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'apple', label: 'Apple'},
        1: {value: 'banana', label: 'Banana'},
        2: {value: 'cherry', label: 'Cherry'}
    }"
    as="collection" />

<ui:select.root collection="{collection}" defaultValue="{0: 'banana'}">
    <ui:select.label>Select a fruit</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose a fruit" />
    </ui:select.control>
    <ui:select.content>
        <ui:select.list>
            <f:for each="{collection.items}" as="item">
                <ui:select.item item="{item}">
                    <ui:select.itemText>{item.label}</ui:select.itemText>
                    <ui:select.itemIndicator />
                </ui:select.item>
            </f:for>
        </ui:select.list>
    </ui:select.content>
</ui:select.root>
```

### Multiple Selection

Allow selecting multiple items.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'react', label: 'React'},
        1: {value: 'vue', label: 'Vue'},
        2: {value: 'angular', label: 'Angular'},
        3: {value: 'svelte', label: 'Svelte'}
    }"
    as="collection" />

<ui:select.root collection="{collection}" multiple="{true}">
    <ui:select.label>Select frameworks</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose frameworks" />
    </ui:select.control>
    <ui:select.content>
        <ui:select.list>
            <f:for each="{collection.items}" as="item">
                <ui:select.item item="{item}">
                    <ui:select.itemText>{item.label}</ui:select.itemText>
                    <ui:select.itemIndicator />
                </ui:select.item>
            </f:for>
        </ui:select.list>
    </ui:select.content>
</ui:select.root>
```

### Disabled Items

Disable specific items in the list.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'available', label: 'Available Option'},
        1: {value: 'unavailable', label: 'Unavailable Option', disabled: true},
        2: {value: 'another', label: 'Another Option'}
    }"
    as="collection" />

<ui:select.root collection="{collection}">
    <ui:select.label>Select an option</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose an option" />
    </ui:select.control>
    <ui:select.content>
        <ui:select.list>
            <f:for each="{collection.items}" as="item">
                <ui:select.item item="{item}">
                    <ui:select.itemText>{item.label}</ui:select.itemText>
                    <ui:select.itemIndicator />
                </ui:select.item>
            </f:for>
        </ui:select.list>
    </ui:select.content>
</ui:select.root>
```

### With Item Groups

Organize items into logical groups.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'apple', label: 'Apple', type: 'Fruits'},
        1: {value: 'banana', label: 'Banana', type: 'Fruits'},
        2: {value: 'carrot', label: 'Carrot', type: 'Vegetables'},
        3: {value: 'broccoli', label: 'Broccoli', type: 'Vegetables'}
    }"
    groupByKey="type"
    as="collection" />

<ui:select.root collection="{collection}">
    <ui:select.label>Select produce</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose produce" />
    </ui:select.control>
    <ui:select.content>
        <ui:select.list>
            <f:for each="{collection.group}" as="group" key="type">
                <ui:select.itemGroup value="{type}">
                    <ui:select.itemGroupLabel>{type}</ui:select.itemGroupLabel>
                    <f:for each="{group}" as="item">
                        <ui:select.item item="{item}">
                            <ui:select.itemText>{item.label}</ui:select.itemText>
                            <ui:select.itemIndicator />
                        </ui:select.item>
                    </f:for>
                </ui:select.itemGroup>
            </f:for>
        </ui:select.list>
    </ui:select.content>
</ui:select.root>
```

### With Form Field

Use with the Field component for form validation.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'us', label: 'United States'},
        1: {value: 'uk', label: 'United Kingdom'},
        2: {value: 'de', label: 'Germany'}
    }"
    as="collection" />

<ui:field.root name="country" required="{true}">
    <ui:select.root collection="{collection}">
        <ui:select.label>Country</ui:select.label>
        <ui:select.control class="min-w-48">
            <ui:select.trigger placeholder="Select your country" />
        </ui:select.control>
        <ui:select.content>
            <ui:select.list>
                <f:for each="{collection.items}" as="item">
                    <ui:select.item item="{item}">
                        <ui:select.itemText>{item.label}</ui:select.itemText>
                        <ui:select.itemIndicator />
                    </ui:select.item>
                </f:for>
            </ui:select.list>
        </ui:select.content>
    </ui:select.root>
    <ui:field.errorText />
</ui:field.root>
```

### With Tabs

By default `content` is a passthrough wrapper around the `list`, and the list carries the listbox role. Set `popupType` to `PopupType::Dialog` (an enum, so `popupType="{f:constant(name: 'Jramke\FluidPrimitives\Enum\PopupType::Dialog')}"`) when the popup also holds other interactive widgets: `content` is then announced as a dialog, and `list` stays the listbox. Place those widgets next to the list inside `content`. Here a few tabs narrow the items down - the select keeps a single list, so the example moves it into the active tab's panel and swaps the machine's collection (hiding the other items) whenever the active tab changes.

**SelectExamples.html**

```html
<ui:listCollection
    items="{
        0: {value: 'apple', label: 'Apple', category: 'fruit'},
        1: {value: 'banana', label: 'Banana', category: 'fruit'},
        2: {value: 'cherry', label: 'Cherry', category: 'fruit'},
        3: {value: 'carrot', label: 'Carrot', category: 'vegetable'},
        4: {value: 'broccoli', label: 'Broccoli', category: 'vegetable'},
        5: {value: 'spinach', label: 'Spinach', category: 'vegetable'}
    }"
    as="collection" />

<ui:select.root
    collection="{collection}"
    popupType="{f:constant(name: 'Jramke\FluidPrimitives\Enum\PopupType::Dialog')}"
    autoMount="{false}"
    rootId="select-with-tabs">
    <ui:select.label>Select produce</ui:select.label>
    <ui:select.control class="min-w-48">
        <ui:select.trigger placeholder="Choose produce" />
    </ui:select.control>
    <ui:select.content>
        <ui:tabs.root defaultValue="all" autoMount="{false}" rootId="select-with-tabs-tabs">
            <ui:tabs.list class="px-3 flex">
                <ui:tabs.trigger class="text-sm" value="all">All</ui:tabs.trigger>
                <ui:tabs.trigger class="text-sm" value="fruit">Fruits</ui:tabs.trigger>
                <ui:tabs.trigger class="text-sm" value="vegetable">Vegetables</ui:tabs.trigger>
            </ui:tabs.list>
            <ui:tabs.content value="all">
                <ui:select.list>
                    <f:for each="{collection.items}" as="item">
                        <ui:select.item item="{item}">
                            <ui:select.itemText>{item.label}</ui:select.itemText>
                            <ui:select.itemIndicator />
                        </ui:select.item>
                    </f:for>
                </ui:select.list>
            </ui:tabs.content>
            <ui:tabs.content value="fruit" />
            <ui:tabs.content value="vegetable" />
        </ui:tabs.root>
    </ui:select.content>
</ui:select.root>

<vite:asset entry="EXT:docs/Resources/Private/Components/ui/SelectExamples/WithTabs.entry.ts" />
```

**WithTabs.entry.ts**

```ts
import { mount } from 'fluid-primitives';
import { Select } from 'fluid-primitives/select';
import { Tabs } from 'fluid-primitives/tabs';

mount('ui:select', 'select-with-tabs', ({ props }) => {
    const select = new Select(props);
    select.init();

    // The select keeps a single listbox, so the tabs share it: the list moves into the active
    // panel, and its keyboard navigation has to skip what the tab hides - swap the machine's
    // collection and hide the rest of the items to match.
    const source = select.api.collection;

    function showCategory(tabs: Tabs, category: string) {
        const panel = tabs.hydrator.queryAll('content').find(el => el.dataset.value === category);
        const listEl = select.hydrator.query('list');
        if (panel && listEl) panel.append(listEl);

        const collection =
            category === 'all'
                ? source
                : source.filter((_itemString, _index, item) => item.category === category);

        select.updateProps({ collection });
        select.hydrator.queryAll('item').forEach(itemEl => {
            itemEl.hidden = !collection.has(itemEl.dataset.value ?? null);
        });
    }

    mount('ui:tabs', 'select-with-tabs-tabs', ({ props }) => {
        const tabs = new Tabs({
            ...props,
            onValueChange: ({ value }) => showCategory(tabs, value),
        });
        tabs.init();
        return tabs;
    });

    return select;
});

```

### Localization

Default clear trigger labels are shipped via XLF and follow the current Site Language. For per-template overrides, pass translated strings through the `translations` prop.

```html
<ui:select.root
    collection="{myCollection}"
    translations="{
        clearTriggerLabel: f:translate(key: 'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:select.clear')
    }"
>
    ...
</ui:select.root>
```

## API Reference

### select.root

Provides shared select state and wraps all related parts. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `collection` | `Domain\Dto\ListCollection` | Yes | `-` | The item collection. |
| `name` | `string` | No | `-` | The `name` attribute of the underlying select. Inherited from a surrounding field when available. |
| `form` | `string` | No | `-` | The associate form of the underlying select. |
| `disabled` | `boolean` | No | `-` | Whether the select is disabled. Inherited from a surrounding field when available. |
| `invalid` | `boolean` | No | `-` | Whether the select is invalid. Inherited from a surrounding field when available. |
| `readOnly` | `boolean` | No | `-` | Whether the select is read-only. Inherited from a surrounding field when available. |
| `required` | `boolean` | No | `-` | Whether the select is required. Inherited from a surrounding field when available. |
| `closeOnSelect` | `boolean` | No | `true` | Whether the select should close after an item is selected. |
| `positioning` | `array` | No | `{     "placement": "bottom-start",     "gutter": 8 }` | The positioning options of the menu. |
| `defaultValue` | `mixed` | No | `-` | The initial default value of the select when rendered. Use when you don't need to control the value of the select. Inherited from a surrounding field when available. |
| `defaultHighlightedValue` | `string` | No | `-` | The initial value of the highlighted item when opened. Use when you don't need to control the highlighted value of the select. |
| `loopFocus` | `boolean` | No | `false` | Whether to loop the keyboard navigation through the options. |
| `multiple` | `boolean` | No | `-` | Whether to allow multiple selection. |
| `defaultOpen` | `boolean` | No | `false` | Whether the select's open state is controlled by the user. |
| `popupType` | `Enum\PopupType` | No | `Listbox` | The kind of popup the select's content is: `listbox` for a regular select, `dialog` when it holds other interactive content. |
| `deselectable` | `boolean` | No | `-` | Whether the value can be cleared by clicking the selected item. |
| `translations` | `array` | No | `-` | Localized select labels. Use `f:translate` for per-template localization overrides when needed. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `rootId` | `string` | No | `-` | The root ID of the component, used for hydration and identification. |
| `ids` | `array` | No | `[]` | The IDs of of the component parts for composition. |
| `autoMount` | `boolean` | No | `true` | Whether the client initializes the component on its own. Set it to false to mount it yourself with `mount()` |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-root` | <uid> |
| `data-invalid` | Present when invalid |
| `data-readonly` | Present when read-only |

### select.label

Labels the select. Renders a `<label>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-label` | <uid> |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-readonly` | Present when read-only |
| `data-required` | Present when required |

### select.control

Groups the trigger and optional clear button. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-control` | <uid> |
| `data-state` | "open" \| "closed" |
| `data-focus` | Present when focused |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |

### select.trigger

Opens and closes the select menu. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-trigger` | <uid> |
| `data-state` | "open" \| "closed" |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-readonly` | Present when read-only |
| `data-placement` | The placement of the trigger |
| `data-align-with-trigger` |  |
| `data-side` | The side of the trigger that the trigger is positioned on |
| `data-placeholder-shown` | Present when placeholder is shown |

### select.valueText

Displays the selected value or placeholder text. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `placeholder` | `string` | No | `-` | The placeholder text to render when no value is selected. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-value-text` | <uid> |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-focus` | Present when focused |

### select.indicator

Displays a decorative indicator for the trigger. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-indicator` | <uid> |
| `data-state` | "open" \| "closed" |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-readonly` | Present when read-only |

### select.clearTrigger

Clears the current selection. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-clear-trigger` | <uid> |
| `data-invalid` | Present when invalid |

### select.positioner

Positions the floating select content. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-positioner` | <uid> |
| `data-nested` | Present when the positioner is nested within another {{widget}} |
| `data-has-nested` | Present when the positioner has nested {{widget}}s |

### select.content

The popup surface, positioned by `positioner`. Holds the `list` and, with `popupType` `dialog`, other widgets next to it. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-content` | <uid> |
| `data-state` | "open" \| "closed" |
| `data-placement` | The placement of the content |
| `data-align-with-trigger` |  |
| `data-side` | The side of the trigger that the content is positioned on |
| `data-nested` | listbox |
| `data-has-nested` | listbox |

### select.list

The listbox inside `content` that holds the options - it takes focus, scrolls and tracks the active option. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-list` | <uid> |
| `data-activedescendant` | The id the active descendant of the list |

### select.itemGroup

Groups related options together. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | Yes | `-` | The value identifier of the item group. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-item-group` | <uid> |
| `data-disabled` | Present when disabled |

### select.itemGroupLabel

Labels a group of related options. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### select.item

Represents a selectable option. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `item` | `mixed` | Yes | `-` | The item to render. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-item` | <uid> |
| `data-value` | The value of the item |
| `data-state` | "checked" \| "unchecked" |
| `data-highlighted` | Present when highlighted |
| `data-disabled` | Present when disabled |

### select.itemText

Displays the text content of an option. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-item-text` | <uid> |
| `data-state` | "checked" \| "unchecked" |
| `data-disabled` | Present when disabled |
| `data-highlighted` | Present when highlighted |

### select.itemIndicator

Displays the selected-state indicator for an option. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-select-item-indicator` | <uid> |
| `data-state` | "checked" \| "unchecked" |

### select.hiddenSelect

Provides the native `<select>` element for form submission. Renders a `<select>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `scrollArrowVisibility` | `"none" \| "top" \| "bottom" \| "both"` | Which scroll arrows should be visible based on the content's scroll position. - `"none"`: content fits, no scrolling needed - `"top"`: scrolled past the top (top arrow visible) - `"bottom"`: more content below (bottom arrow visible) - `"both"`: scrolled somewhere in the middle (both arrows visible) |
| `focused` | `boolean` | Whether the select is focused |
| `open` | `boolean` | Whether the select is open |
| `empty` | `boolean` | Whether the select value is empty |
| `highlightedValue` | `string \| null` | The value of the highlighted item |
| `highlightedItem` | `V \| null` | The highlighted item |
| `setHighlightValue` | `(value: string) => void` | Function to highlight a value |
| `clearHighlightValue` | `VoidFunction` | Function to clear the highlighted value |
| `selectedItems` | `V[]` | The selected items |
| `hasSelectedItems` | `boolean` | Whether there's a selected option |
| `value` | `string[]` | The selected item keys |
| `valueAsString` | `string` | The string representation of the selected items |
| `selectValue` | `(value: string) => void` | Function to select a value |
| `selectAll` | `VoidFunction` | Function to select all values |
| `setValue` | `(value: string[]) => void` | Function to set the value of the select |
| `clearValue` | `(value?: string) => void` | Function to clear the value of the select. If a value is provided, it will only clear that value, otherwise, it will clear all values. |
| `focus` | `VoidFunction` | Function to focus on the select input |
| `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a select item |
| `setOpen` | `(open: boolean) => void` | Function to open or close the select |
| `collection` | `ListCollection<V>` | Function to toggle the select |
| `reposition` | `(options?: Partial<PositioningOptions>) => void` | Function to set the positioning options of the select |
| `multiple` | `boolean` | Whether the select allows multiple selections |
| `disabled` | `boolean` | Whether the select is disabled |
| `getRootState` | `() => RootState` | Returns the state of the root |
| `getTriggerState` | `() => TriggerState` | Returns the state of the trigger |
| `getContentState` | `() => ContentState` | Returns the state of the content |

### Accessibility

| Key | Description |
| --- | --- |
| `Space`  | <span>When focus is on trigger, opens the select and focuses the first selected item.<br />When focus is on the content, selects the highlighted item.</span> |
| `Enter`  | <span>When focus is on trigger, opens the select and focuses the first selected item.<br />When focus is on content, selects the focused item.</span> |
| `ArrowDown`  | <span>When focus is on trigger, opens the select.<br />When focus is on content, moves focus to the next item.</span> |
| `ArrowUp`  | <span>When focus is on trigger, opens the select.<br />When focus is on content, moves focus to the previous item.</span> |
| `Esc`  | <span>Closes the select and moves focus to trigger.</span> |
| `A-Z` `a-z`  | <span>When focus is on trigger, selects the item whose label starts with the typed character.<br />When focus is on the listbox, moves focus to the next item with a label that starts with the typed character.</span> |
