# 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)

**Select.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>
        <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.content>
</ui:select.root>
```

**Select.ts**

```ts
import { mountAll } from 'fluid-primitives';
import { Select } from 'fluid-primitives/select';

mountAll('select', ({ props }) => {
    // @ts-expect-error
    const select = new Select(props);
    select.init();
    return select;
});

```

## 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
- Works with Field component for form integration
- Supports custom positioning

## Installation

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

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives.com/tree/main/packages/docs/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.

**Select.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>
        <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.content>
</ui:select.root>
```

### Multiple Selection

Allow selecting multiple items.

**Select.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>
        <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.content>
</ui:select.root>
```

### Disabled Items

Disable specific items in the list.

**Select.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>
        <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.content>
</ui:select.root>
```

### With Item Groups

Organize items into logical groups.

**Select.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>
        <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.content>
</ui:select.root>
```

### With Form Field

Use with the Field component for form validation.

**Select.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>
            <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.content>
    </ui:select.root>
    <ui:field.error />
</ui:field.root>
```

### 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. Set `clearTriggerLabel` to `{false}` or an empty string to omit the `aria-label`.

```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. |
| `composite` | `boolean` | No | `true` | Whether the select is composed with other composite widgets like tabs or combobox. |
| `deselectable` | `boolean` | No | `-` | Whether the value can be cleared by clicking the selected item. |
| `translations` | `array` | No | `-` | Localized select labels. Set entries to `` to omit the corresponding `aria-label`. Use `f:translate` for per-template localization overrides when needed. |
| `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. |
| `controlled` | `boolean` | No | `false` | If true, the component is meant to be initialized manually inside another component |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | root |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | label |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | control |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | trigger |
| `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-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. |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | value-text |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | indicator |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | clear-trigger |
| `data-invalid` | Present when invalid |

### select.positioner

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

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

### select.content

Contains the selectable options. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | content |
| `data-state` | "open" \| "closed" |
| `data-nested` | listbox |
| `data-has-nested` | listbox |
| `data-placement` | The placement of the content |
| `data-side` | The side of the trigger that the content is positioned on |
| `data-activedescendant` | The id the active descendant of the content |

### 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. |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | item-group |
| `data-disabled` | Present when disabled |

### select.itemGroupLabel

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

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

### select.item

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

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `item` | `mixed` | Yes | `-` | The item to render. |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | item |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | item-text |
| `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 |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | select |
| `data-part` | item-indicator |
| `data-state` | "checked" \| "unchecked" |

### select.hiddenSelect

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

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `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. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `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 |

### 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> |

## Anatomy

```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.item>
                <primitives:select.itemText />
                <primitives:select.itemIndicator />
            </primitives:select.item>
            <primitives:select.itemGroup>
                <primitives:select.itemGroupLabel />
            </primitives:select.itemGroup>
        </primitives:select.content>
    </primitives:select.positioner>
    <primitives:select.hiddenSelect />
</primitives:select.root>
```
