Select
Listbox for picking one option.
Usage
Compose Select.Root, Select.Trigger, Select.Content, and Select.Item. The content
portals to the body, so it escapes overflow clipping.
States
Individual items can be disabled while the rest remain interactive.
Props
Select.Root
| Prop | Type | Default |
|---|---|---|
allowDeselect bits-ui Whether to allow the user to deselect an item by clicking on an already selected item. This is only applicable to `type="single"` selects/comboboxes. | boolean | undefined | — |
autocomplete bits-ui The autocomplete attribute to forward to the hidden input element. | FullAutoFill | null | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
disabled bits-ui Whether the combobox is disabled. | boolean | undefined | `false` |
items bits-ui Optionally provide an array of `value` and `label` pairs that will be used to match and trigger selection when the trigger is focused and a key is pressed while the content is closed. It's also used to handle form autofill. By providing this value, you enable selecting a value when the trigger is focused and a key is pressed without the content being open, similar to how a native `<select>` works. For this to work, you must The label is what the user will potentially search for via typeahead, and the value is what is set as the selected value when a typeahead match is found. We can't rely on the individual `Item` components to do this because they may not ever be mounted to do the DOM if using a conditional block with a Svelte transition or certain animation libraries. IMPORTANT: This functionality is only available for single-select listboxes. | { value: string; label: string; disabled?: boolean | undefined; }[] | undefined | — |
loop bits-ui Whether or not the combobox menu should loop through the items when navigating with the keyboard. | boolean | undefined | `false` |
name bits-ui The name to apply to the hidden input element for form submission. If not provided, a hidden input will not be rendered and the combobox will not be part of a form. | string | undefined | — |
onOpenChange bits-ui A callback function called when the open state changes. | OnChangeFn<boolean> | undefined | — |
onOpenChangeComplete bits-ui A callback function called when the open state changes and the animation is complete. | OnChangeFn<boolean> | undefined | — |
onValueChange bits-ui A callback function called when the value changes. | OnChangeFn<string> | OnChangeFn<string[]> | undefined | — |
open bits-ui Whether the combobox popover is open. | boolean | undefined | `false` |
required bits-ui Whether the combobox is required (for form submission). | boolean | undefined | `false` |
scrollAlignment bits-ui How to scroll the combobox items into view when navigating with the keyboard. | "center" | "nearest" | undefined | `"nearest"` |
type required bits-ui The type of combobox. | "multiple" | "single" | — |
value bits-ui The value of the selected combobox item. | string | string[] | undefined | — |
Select.Trigger
| Prop | Type | Default |
|---|---|---|
invalid Marks the control as failing validation. Always applies the invalid styling. Does NOT set `aria-invalid`: this renders as `button`, and ARIA does not support the attribute there, so assistive technology is free to ignore it. axe does NOT flag it either way — verified by injecting it and watching the suite still pass — so this is a decision taken from the spec, not one a tool enforces. The accessible signal comes from `Field` wiring the error message through `aria-describedby`. Prefer letting `Field` drive this: passing `Field` an `error` is what makes a field invalid, so the message the user reads and the state of the control cannot disagree. | boolean | false |
required Accepted and deliberately NOT forwarded. This renders as a `<button>`. A native `required` attribute is inert there, and `aria-required` is worse — axe reports it as an `aria-allowed-attr` violation, verified rather than assumed. (Note `aria-invalid` differs: axe accepts that one on a button. The two rules are not the same.) So it is swallowed here rather than emitted as dead markup. When wrapped by `Field`, the required signal a user gets is the marker on the visible label plus the error on submit — which is what `Field` is for. | boolean | false |
class | string | — |
children | Snippet | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
id bits-ui | string | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Select.Content
| Prop | Type | Default |
|---|---|---|
class | string | — |
align bits-ui The preferred alignment of the anchor to render against when open. This may change when collisions occur. | "start" | "center" | "end" | undefined | — |
alignOffset bits-ui An offset in pixels from the "start" or "end" alignment options. | number | undefined | — |
arrowPadding bits-ui This describes the padding between the arrow and the edges of the floating element. If your floating element has border-radius, this will prevent it from overflowing the corners. | number | undefined | — |
avoidCollisions bits-ui When `true`, overrides the `side` and `align` options to prevent collisions with the boundary edges. | boolean | undefined | true |
child bits-ui | Snippet<[FloatingContentSnippetProps & { props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
collisionBoundary bits-ui A boundary element or array of elements to check for collisions against. | Arrayable<Boundary> | undefined | — |
collisionPadding bits-ui The amount in pixels of virtual padding around the viewport edges to check for overflow which will cause a collision. | number | Partial<Record<"top" | "right" | "bottom" | "left", number>> | undefined | 8 |
customAnchor bits-ui Use an element other than the trigger to anchor the content to. If provided, the content will be anchored to the provided element instead of the trigger. You can pass a selector string or an HTMLElement. | string | HTMLElement | Measurable | null | undefined | — |
dir bits-ui The text direction of the content. | Direction | undefined | — |
escapeKeydownBehavior bits-ui Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press. | EscapeBehaviorType | undefined | `close` |
forceMount bits-ui Whether to force mount the component. | boolean | undefined | — |
hideWhenDetached bits-ui | boolean | undefined | — |
id bits-ui | string | undefined | — |
interactOutsideBehavior bits-ui Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction. | InteractOutsideBehaviorType | undefined | `close` |
loop bits-ui Whether or not to loop through the items when navigating with the keyboard. | boolean | undefined | `false` |
onEscapeKeydown bits-ui Callback fired when escape is pressed. | ((e: KeyboardEvent) => void) | undefined | — |
onFocusOutside bits-ui Callback fired when focus leaves the dismissible layer. | ((event: FocusEvent) => void) | undefined | — |
onInteractOutside bits-ui Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device. | InteractOutsideEventHandler | undefined | — |
preventOverflowTextSelection bits-ui Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer. | boolean | undefined | `true` |
preventScroll bits-ui Whether to prevent scrolling the body when the content is open. Whether to prevent body scrolling when the content is open. | boolean | undefined | true |
ref bits-ui | HTMLElement | null | undefined | — |
side bits-ui The preferred side of the anchor to render against when open. Will be reversed when collisions occur. | "top" | "right" | "bottom" | "left" | undefined | — |
sideOffset bits-ui The distance in pixels from the anchor to the floating element. | number | undefined | — |
sticky bits-ui | "partial" | "always" | undefined | — |
strategy bits-ui The positioning strategy to use for the floating element. | "absolute" | "fixed" | undefined | — |
updatePositionStrategy bits-ui "optimized" will only update the position when necessary, while "always" will update the position on each animation frame, which is useful if the floating content is following something like a mouse cursor. | "always" | "optimized" | undefined | "optimized" |
Select.Item
| Prop | Type | Default |
|---|---|---|
class | string | — |
child bits-ui | Snippet<[SelectItemSnippetProps & { props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[SelectItemSnippetProps]> | undefined | — |
disabled bits-ui Whether the item is disabled. | boolean | undefined | `false` |
id bits-ui | string | undefined | — |
label bits-ui The label of the item. If provided, this is the item that users will search for. If not provided, the value will be used as the label. | string | undefined | — |
onHighlight bits-ui A callback function called when the item is highlighted. This can be used as a replacement for `onfocus` since we don't actually focus the item and instead rely on the `aria-activedescendant` attribute to indicate the highlighted item. | (() => void) | undefined | — |
onUnhighlight bits-ui A callback function called when the item is unhighlighted. This can be used as a replacement for `onblur` since we don't actually focus the item and instead rely on the `aria-activedescendant` attribute to indicate the highlighted item. | (() => void) | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
value required bits-ui The value of the item. | string | — |
All subcomponents also forward their corresponding Bits props via spreading.