Select
View as MarkdownA common form component for choosing a predefined value in a dropdown menu.
<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>
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
typo3 ui:add select
Please copy the files manually from GitHub into your project.
Read more about installing Components and Primitives.
Examples
Default Value
Set an initial selected value.
<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.
<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.
<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.
<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.
<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.
<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
The following tables cover the available props of the Fluid Primitives. For a full list of available client side props and methods, see the Zag.js Machine API.
select.root
Provides shared select state and wraps all related parts. Renders a <div> element.
| Name | Description | Required | Default |
|---|---|---|---|
collection | Domain\Dto\ListCollectionThe item collection. | Yes | - |
name | stringThe `name` attribute of the underlying select. Inherited from a surrounding field when available. | No | - |
form | stringThe associate form of the underlying select. | No | - |
disabled | booleanWhether the select is disabled. Inherited from a surrounding field when available. | No | - |
invalid | booleanWhether the select is invalid. Inherited from a surrounding field when available. | No | - |
readOnly | booleanWhether the select is read-only. Inherited from a surrounding field when available. | No | - |
required | booleanWhether the select is required. Inherited from a surrounding field when available. | No | - |
closeOnSelect | booleanWhether the select should close after an item is selected. | No | true |
positioning | arrayThe positioning options of the menu. | No | {
"placement": "bottom-start",
"gutter": 8
} |
defaultValue | mixedThe 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. | No | - |
defaultHighlightedValue | stringThe initial value of the highlighted item when opened. Use when you don't need to control the highlighted value of the select. | No | - |
loopFocus | booleanWhether to loop the keyboard navigation through the options. | No | false |
multiple | booleanWhether to allow multiple selection. | No | - |
defaultOpen | booleanWhether the select's open state is controlled by the user. | No | false |
composite | booleanWhether the select is composed with other composite widgets like tabs or combobox. | No | true |
deselectable | booleanWhether the value can be cleared by clicking the selected item. | No | - |
translations | arrayLocalized select labels. Set entries to `` to omit the corresponding `aria-label`. Use `f:translate` for per-template localization overrides when needed. | No | - |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
rootId | stringThe root ID of the component, used for hydration and identification. | No | - |
ids | arrayThe IDs of of the component parts for composition. | No | [] |
controlled | booleanIf true, the component is meant to be initialized manually inside another component | No | false |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
placeholder | stringThe placeholder text to render when no value is selected. | No | - |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
select.content
Contains the selectable options. Renders a <div> element.
| Name | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
value | stringThe value identifier of the item group. | Yes | - |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
select.item
Represents a selectable option. Renders a <div> element.
| Name | Description | Required | Default |
|---|---|---|---|
item | mixedThe item to render. | Yes | - |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | Description | Required | Default |
|---|---|---|---|
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
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 | When focus is on trigger, opens the select and focuses the first selected item. When focus is on the content, selects the highlighted item. |
Enter | When focus is on trigger, opens the select and focuses the first selected item. When focus is on content, selects the focused item. |
ArrowDown | When focus is on trigger, opens the select. When focus is on content, moves focus to the next item. |
ArrowUp | When focus is on trigger, opens the select. When focus is on content, moves focus to the previous item. |
Esc | Closes the select and moves focus to trigger. |
A-Za-z | When focus is on trigger, selects the item whose label starts with the typed character. When focus is on the listbox, moves focus to the next item with a label that starts with the typed character. |
Anatomy
<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>