Select
A common form component for choosing a predefined value in a dropdown menu.
Usage guidelines
- Prefer Combobox for large lists: Select is not filterable, aside from basic keyboard typeahead functionality to find items by focusing and highlighting them. Prefer Combobox instead of Select when the number of items is sufficiently large to warrant filtering.
- Special positioning behavior: The select popup by default overlaps its trigger so the selected item's text is aligned with the trigger's value text. This behavior can be disabled or customized.
- Form controls must have an accessible name: Prefer
<Select.Label>, or provide anaria-labelon<Select.Trigger>when no visible label is rendered. See Labeling a select and the forms guide. - Closing animations: The popup stays rendered until its closing animation finishes. See Svelte transitions for animating it with Svelte transitions and Manual unmounting for manual control.
Anatomy
Import the component and assemble its parts:
Positioning
<Select.Positioner> has a special prop called alignItemWithTrigger which causes the positioning to act differently by default from other Positioner components.
The prop makes the select popup overlap the trigger so the selected item's text is aligned with the trigger's value text.
For styling, data-side is "none" on the .Popup and .Positioner parts when the mode is active.
To prevent the select popup from overlapping its trigger, set the alignItemWithTrigger prop to false.
When set to true (its default) there are a few important points to note about its behavior:
- Interaction type dependent: For UX reasons, the
alignItemWithTriggerpositioning mode is disabled if touch was the pointer type used to open the popup. - Viewport space dependent: There must be enough space in the viewport to align the selected item's text with the trigger's value text without causing the popup to be too vertically small - otherwise, it falls back to the default positioning mode.
This can be customized by setting
min-heighton the<Select.Positioner>element; a smaller value will fallback less often. Additionally, the trigger must be at least 20px from the edges of the top and bottom of the viewport, or it will also fall back. - Other positioning props are ignored: Props like
sideoralignhave no effect unless the prop is set tofalseor when in fallback mode.
Examples
Typed wrapper component
The following example shows a typed wrapper around the Select component with correct type inference and type safety:
Formatting the value
By default, the <Select.Value> component renders the raw value.
Passing the items prop to <Select.Root> instead renders the matching label for the rendered value:
A snippet can also be passed as the children of <Select.Value> to render a formatted value:
To avoid lookup, object values for each item can also be used.
Labeling a select
Use <Select.Label> to provide a visible label for the select trigger:
<Select.Label> renders a <div>, so clicking it focuses the select trigger without opening the popup.
Placeholder values
To show a placeholder value, use the placeholder prop on <Select.Value>:
With placeholders, users cannot clear selected values using the select itself. If the select value should be clearable from the popup (instead of an external "reset" button), use a null item rendered in the list itself:
Multiple selection
Add the multiple prop to the <Select.Root> component to allow multiple selections.
Object values
Select items can use objects as values instead of primitives.
This lets you access the full object in custom render functions, and can avoid needing to specify items for lookup.
Grouped
Organize related options with <Select.Group> and <Select.GroupLabel> to add section headings inside the popup.
Groups are represented by an array of objects with an items property, which itself is an array of individual items for each group. An extra property, such as value, can be provided for the heading text when rendering the group label.
API reference
Root
Groups all parts of the select. Renders no element of its own, only the hidden inputs a form submits and validates.
value SelectValueOf<Value, Multiple> —
- Name
- Description
The selected value. Use
bind:valueto share it with the parent. Without a binding it starts fromdefaultValue.- Type
SelectValueOf<Value, Multiple>- Binding
bind:value
defaultValue SelectValueOf<Value, Multiple> null, or [] when `multiple`
- Name
- Description
The value the select starts with and the value a form reset restores.
- Type
SelectValueOf<Value, Multiple>- Default
null, or [] when `multiple`
onValueChange function —
- Name
- Description
Called before the value changes. Call
eventDetails.cancel()to keep the current value.- Type
(value: SelectValueOf<Value, Multiple>, eventDetails: SelectChangeEventDetails) => void
open boolean false
- Name
- Description
Whether the popup is open. Use
bind:opento share it with the parent.- Type
boolean- Default
false- Binding
bind:open
onOpenChange function —
- Name
- Description
Called before the popup opens or closes. Call
eventDetails.cancel()to veto it.- Type
(open: boolean, eventDetails: SelectOpenChangeEventDetails) => void
onOpenChangeComplete function —
- Name
- Description
Called after the open or close animations finish.
- Type
(open: boolean) => void
name string —
- Name
- Description
Identifies the field when a form is submitted.
- Type
string
form string —
- Name
- Description
Id of the form the hidden inputs belong to, for a select rendered outside it.
- Type
string
autocomplete FullAutoFill | null —
- Name
- Description
A hint for browser autofill, on the hidden input.
- Type
FullAutoFill | null
id string —
- Name
- Description
The id of the select. The trigger takes it.
- Type
string
required boolean false
- Name
- Description
Whether a value must be chosen before the form submits.
- Type
boolean- Default
false
readonly boolean false
- Name
- Description
Whether the user can browse the options but not choose a different one.
- Type
boolean- Default
false
disabled boolean false
- Name
- Description
Whether the select ignores user interaction.
- Type
boolean- Default
false
multiple Multiple false
- Name
- Description
Whether several items can be selected.
- Type
Multiple- Default
false
highlightItemOnHover boolean true
- Name
- Description
Whether moving the pointer over items highlights them. Set
falseto tell CSS:hoverapart from thedata-highlightedstate.- Type
boolean- Default
true
modal boolean true
- Name
- Description
Whether the select is modal while open: page scroll is locked and outside pointer interaction is blocked. On touch devices the page stays scrollable unless the popup spans nearly the full viewport width.
- Type
boolean- Default
true
items Record<string, string | null | undefined> | ReadonlyArray<LabeledItem> | ReadonlyArray<Group<LabeledItem>> | undefined —
- Name
- Description
The items of the popup, so
Select.Valueshows the selected item's label instead of its value: a record of labels by value, an array of{ value, label }, or groups of them.- Type
Record<string, string | null | undefined> | ReadonlyArray<LabeledItem> | ReadonlyArray<Group<LabeledItem>> | undefined
itemToStringLabel function —
- Name
- Description
Converts an object value to the label
Select.Valueshows. A{ value, label }object uses itslabelwithout it.- Type
(itemValue: Value) => string
itemToStringValue function —
- Name
- Description
Converts an object value to the string a form submits. A
{ value, label }object uses itsvaluewithout it.- Type
(itemValue: Value) => string
isItemEqualToValue function Object.is
- Name
- Description
Whether an item value matches the selected value. Use it for object values that are not the same reference.
- Type
(itemValue: Value, value: Value) => boolean- Default
Object.is
Label
An accessible label that is automatically associated with the select trigger. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: FieldRootState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: FieldRootState, children: Snippet | undefined]>
Trigger
A button that opens the select popup. Renders a <button> element.
disabled boolean | null —
- Name
- Description
Whether the trigger ignores user interaction.
- Type
boolean | null
nativeButton boolean true
- Name
- Description
Whether the host is a native
<button>. Setfalsewhenrendersupplies a non-button element.- Type
boolean- Default
true
id string | null —
- Name
- Description
The trigger's id. Defaults to the root's id.
- Type
string | null
render Snippet<[props: HTMLButtonAttributes, state: SelectTriggerState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLButtonAttributes, state: SelectTriggerState, children: Snippet | undefined]>
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
readOnly boolean
- Name
readOnly- Description
Whether the select is read-only.
- Type
boolean
popupSide Side | null
- Name
popupSide- Description
The side the popup is placed on, while it is mounted.
- Type
Side | null
value unknown
- Name
value- Description
The selected value.
- Type
unknown
placeholder boolean
- Name
placeholder- Description
Whether the select has no value.
- Type
boolean
disabled boolean
- Name
disabled- Description
Whether the component should ignore user interaction.
- Type
boolean
touched boolean
- Name
touched- Description
Whether the field has been touched.
- Type
boolean
dirty boolean
- Name
dirty- Description
Whether the field value has changed from its initial value.
- Type
boolean
valid boolean | null
- Name
valid- Description
Whether the field is valid.
nullmeans validity is not known yet.- Type
boolean | null
filled boolean
- Name
filled- Description
Whether the field has a value.
- Type
boolean
focused boolean
- Name
focused- Description
Whether the field is focused.
- Type
boolean
data-popup-open
data-popup-side
data-pressed
data-disabled
data-readonly
data-required
data-valid
data-invalid
data-dirty
data-touched
data-filled
data-focused
data-placeholder
Value
The text label of the selected item. Renders a <span> element.
placeholder string —
- Name
- Description
Shown while nothing is selected.
children, or anullitem's label initems, replaces it.- Type
string
children Snippet<[value: unknown]> —
- Name
- Description
Formats the selected value. Treat the value as read-only.
- Type
Snippet<[value: unknown]>
render Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectValueState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectValueState, children: Snippet | undefined]>
value unknown
- Name
value- Description
The selected value.
- Type
unknown
placeholder boolean
- Name
placeholder- Description
Whether the placeholder shows.
- Type
boolean
data-placeholder
Icon
An icon that shows the trigger opens a select popup. Renders a <span> element.
render Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectIconState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectIconState, children: Snippet | undefined]>
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
data-popup-open
Backdrop
An overlay displayed beneath the select popup. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectBackdropState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectBackdropState, children: Snippet | undefined]>
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
transitionStatus 'starting' | 'ending' | 'idle' | undefined
- Name
transitionStatus- Type
'starting' | 'ending' | 'idle' | undefined
data-open
data-closed
data-starting-style
data-ending-style
Portal
A portal element that moves the popup to a different part of the DOM. By default, the portal element is appended to <body>.
container HTMLElement | ShadowRoot | null —
- Name
- Description
Element the portal is appended to.
undefineduses the parent portal ordocument.body.nullwaits and does not mount until an element or shadow root is set. There is no ref object.- Type
HTMLElement | ShadowRoot | null
render Snippet<[props: HTMLAttributes<HTMLDivElement> & Record<symbol, Attachment<HTMLDivElement>>, state: SelectPortalState, children: Snippet | undefined]> —
- Name
- Description
Replace the portal element. Host props include the move attachment.
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement> & Record<symbol, Attachment<HTMLDivElement>>, state: SelectPortalState, children: Snippet | undefined]>
Positioner
Positions the select popup. Renders a <div> element.
alignItemWithTrigger boolean true
- Name
- Description
Whether the positioner overlaps the trigger so the selected item's text lines up with the trigger's value. Mouse and keyboard only. It turns itself off when there is not enough space.
- Type
boolean- Default
true
anchor Anchor —
- Name
- Description
An element to position the popup against. Defaults to the trigger.
- Type
Anchor
positionMethod "absolute" | "fixed" 'absolute'
- Name
- Description
Which CSS
positionthe positioner uses.- Type
"absolute" | "fixed"- Default
'absolute'
side Side 'bottom'
- Name
- Description
Which side of the anchor to place the popup on. It can flip to avoid collisions.
- Type
Side- Default
'bottom'
align Align 'center'
- Name
- Description
How to align the popup on its side.
- Type
Align- Default
'center'
sideOffset number | OffsetFunction 0
- Name
- Description
Distance between the anchor and the popup in pixels, or a function of the anchor and positioner sizes, side and alignment.
- Type
number | OffsetFunction- Default
0
alignOffset number | OffsetFunction 0
- Name
- Description
Offset along the alignment axis in pixels, or a function like
sideOffset.- Type
number | OffsetFunction- Default
0
collisionBoundary Boundary 'clipping-ancestors'
- Name
- Description
The area the popup is confined to.
- Type
Boundary- Default
'clipping-ancestors'
collisionPadding Padding 5
- Name
- Description
Space to keep from the edge of the collision boundary.
- Type
Padding- Default
5
arrowPadding number 5
- Name
- Description
Minimum distance between the arrow and the edges of the popup.
- Type
number- Default
5
sticky boolean false
- Name
- Description
Whether the popup stays in the viewport after the anchor scrolls out of view.
- Type
boolean- Default
false
disableAnchorTracking boolean —
- Description
Whether the popup stops following layout shifts of its anchor. Defaults to
truewhile the popup overlaps the trigger.- Type
boolean
collisionAvoidance CollisionAvoidance —
- Name
- Description
How the popup avoids collisions. Dropdowns flip on the side axis and shift on the alignment axis.
- Type
CollisionAvoidance
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectPositionerState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectPositionerState, children: Snippet | undefined]>
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
side Side | 'none'
- Name
side- Description
The side of the anchor the popup is placed on.
nonewhile it overlaps the trigger.- Type
Side | 'none'
align Align
- Name
align- Description
The alignment of the popup relative to the anchor.
- Type
Align
anchorHidden boolean
- Name
anchorHidden- Description
Whether the anchor is hidden.
- Type
boolean
data-open
data-closed
data-anchor-hidden
data-align
data-side
--anchor-height
--anchor-width
--available-height
--available-width
--transform-origin
Popup
A container for the select list. Renders a <div> element.
finalFocus SelectFocusTarget —
- Name
- Description
The element to focus when the popup closes.
falsedoes not move focus,trueuses the default (the trigger), and a function receives the close interaction type.- Type
SelectFocusTarget
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectPopupState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectPopupState, children: Snippet | undefined]>
side Side | 'none'
- Name
side- Description
The side of the anchor the popup is placed on.
- Type
Side | 'none'
align Align
- Name
align- Description
The alignment of the popup relative to the anchor.
- Type
Align
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
transitionStatus 'starting' | 'ending' | 'idle' | undefined
- Name
transitionStatus- Type
'starting' | 'ending' | 'idle' | undefined
data-open
data-closed
data-align
data-side
data-starting-style
data-ending-style
List
A container for the select items, inside the popup. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectListState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectListState, children: Snippet | undefined]>
Arrow
Displays an element positioned against the select anchor. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectArrowState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectArrowState, children: Snippet | undefined]>
open boolean
- Name
open- Description
Whether the popup is open.
- Type
boolean
side Side | 'none'
- Name
side- Description
The side of the anchor the popup is placed on.
- Type
Side | 'none'
align Align
- Name
align- Description
The alignment of the popup relative to the anchor.
- Type
Align
uncentered boolean
- Name
uncentered- Description
Whether the arrow cannot be centered on the anchor.
- Type
boolean
data-open
data-closed
data-uncentered
data-align
data-side
Item
An option in the select popup. Renders a <div> element.
value unknown null
- Name
- Description
The value this item selects.
- Type
unknown- Default
null
label string —
- Name
- Description
The text typeahead matches. Defaults to the item text.
- Type
string
disabled boolean | null false
- Name
- Description
Whether the item ignores user interaction.
- Type
boolean | null- Default
false
nativeButton boolean false
- Name
- Description
Whether the host is a native
<button>.- Type
boolean- Default
false
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectItemState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectItemState, children: Snippet | undefined]>
disabled boolean
- Name
disabled- Description
Whether the item ignores user interaction.
- Type
boolean
selected boolean
- Name
selected- Description
Whether the item is selected.
- Type
boolean
highlighted boolean
- Name
highlighted- Description
Whether the item is highlighted.
- Type
boolean
data-selected
data-highlighted
data-disabled
ItemText
The text label of a select item. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectItemTextState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectItemTextState, children: Snippet | undefined]>
ItemIndicator
Indicates whether the select item is selected. Renders a <span> element.
keepMounted boolean false
- Name
- Description
Whether the indicator stays in the DOM while the item is not selected.
- Type
boolean- Default
false
render Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectItemIndicatorState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLSpanElement>, state: SelectItemIndicatorState, children: Snippet | undefined]>
selected boolean
- Name
selected- Description
Whether the item is selected.
- Type
boolean
transitionStatus 'starting' | 'ending' | 'idle' | undefined
- Name
transitionStatus- Type
'starting' | 'ending' | 'idle' | undefined
data-starting-style
data-ending-style
Group
Groups related select items with their label. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectGroupState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectGroupState, children: Snippet | undefined]>
GroupLabel
The label of a select group. Renders a <div> element.
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectGroupLabelState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectGroupLabelState, children: Snippet | undefined]>
ScrollUpArrow
Scrolls the select list up while the pointer rests on it. Renders a <div> element.
keepMounted boolean false
- Name
- Description
Whether the arrow stays in the DOM while the list cannot scroll that way.
- Type
boolean- Default
false
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectScrollArrowState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectScrollArrowState, children: Snippet | undefined]>
direction 'up' | 'down'
- Name
direction- Description
Which way the arrow scrolls.
- Type
'up' | 'down'
visible boolean
- Name
visible- Description
Whether the list can scroll that way.
- Type
boolean
side Side | 'none'
- Name
side- Description
The side of the anchor the popup is placed on.
- Type
Side | 'none'
transitionStatus 'starting' | 'ending' | 'idle' | undefined
- Name
transitionStatus- Type
'starting' | 'ending' | 'idle' | undefined
data-direction
data-side
data-visible
data-starting-style
data-ending-style
ScrollDownArrow
Scrolls the select list down while the pointer rests on it. Renders a <div> element.
keepMounted boolean false
- Name
- Description
Whether the arrow stays in the DOM while the list cannot scroll that way.
- Type
boolean- Default
false
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectScrollArrowState, children: Snippet | undefined]> —
- Name
- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SelectScrollArrowState, children: Snippet | undefined]>
direction 'up' | 'down'
- Name
direction- Description
Which way the arrow scrolls.
- Type
'up' | 'down'
visible boolean
- Name
visible- Description
Whether the list can scroll that way.
- Type
boolean
side Side | 'none'
- Name
side- Description
The side of the anchor the popup is placed on.
- Type
Side | 'none'
transitionStatus 'starting' | 'ending' | 'idle' | undefined
- Name
transitionStatus- Type
'starting' | 'ending' | 'idle' | undefined
data-direction
data-side
data-visible
data-starting-style
data-ending-style
Separator
A visual separator between select items or groups. Renders a <div> element.
orientation "horizontal" | "vertical" 'horizontal'
- Name
- Description
The orientation of the separator.
- Type
"horizontal" | "vertical"- Default
'horizontal'
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SeparatorState, children: Snippet | undefined]> —
- Name
- Description
Replace the default
<div>. Spreadpropsonto the host element.- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SeparatorState, children: Snippet | undefined]>
orientation 'horizontal' | 'vertical'
- Name
orientation- Description
The orientation of the separator.
- Type
'horizontal' | 'vertical'