Select
Choose one value from a trigger-controlled popup list.
Usage
Environment
Choose one deployment environment from a popup collection.
Choose one deployment environment from a popup collection.
<!-- Select / Environment -->
<script setup lang="ts">
import { SelectRoot, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectItemIndicator } from '@sectile/vue/select'
const environments = [
{ id: 'production', label: 'Production', detail: 'customer.app' },
{ id: 'staging', label: 'Staging', detail: 'staging.customer.app' },
{ id: 'development', label: 'Development', detail: 'Local workspace' },
]
const environmentIDs = environments.map(({ id }) => id)
const environmentLabel = (id: string) => environments.find(item => item.id === id)?.label ?? id
</script>
<template>
<SelectRoot :items="environmentIDs" :text-value="environmentLabel" default-value="production">
<SelectTrigger><SelectValue placeholder="Choose an environment" /></SelectTrigger>
<SelectContent>
<SelectItem v-for="item in environments" :key="item.id" :value="item.id">
<strong>{{ item.label }}</strong>
<small>{{ item.detail }}</small>
<SelectItemIndicator>✓</SelectItemIndicator>
</SelectItem>
</SelectContent>
</SelectRoot>
</template>Disabled option
Show an unavailable option without allowing focus or selection to land on it.
Show an unavailable option without allowing focus or selection to land on it.
<!-- Select / Disabled Option -->
<script setup lang="ts">
import { SelectRoot, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectItemIndicator } from '@sectile/vue/select'
const environments = [
{ id: 'production', label: 'Production', detail: 'customer.app' },
{ id: 'staging', label: 'Staging', detail: 'staging.customer.app' },
{ id: 'development', label: 'Development', detail: 'Local workspace' },
]
const environmentIDs = environments.map(({ id }) => id)
const environmentLabel = (id: string) => environments.find(item => item.id === id)?.label ?? id
</script>
<template>
<SelectRoot :items="environmentIDs" :text-value="environmentLabel" default-value="production">
<SelectTrigger><SelectValue placeholder="Choose an environment" /></SelectTrigger>
<SelectContent>
<SelectItem v-for="item in environments" :key="item.id" :value="item.id">
<strong>{{ item.label }}</strong>
<small>{{ item.detail }}</small>
<SelectItemIndicator>✓</SelectItemIndicator>
</SelectItem>
</SelectContent>
</SelectRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Select / Controlled -->
<script setup lang="ts">
import { SelectRoot, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectItemIndicator } from '@sectile/vue/select'
const environments = [
{ id: 'production', label: 'Production', detail: 'customer.app' },
{ id: 'staging', label: 'Staging', detail: 'staging.customer.app' },
{ id: 'development', label: 'Development', detail: 'Local workspace' },
]
const environmentIDs = environments.map(({ id }) => id)
const environmentLabel = (id: string) => environments.find(item => item.id === id)?.label ?? id
</script>
<template>
<SelectRoot :items="environmentIDs" :text-value="environmentLabel" default-value="production">
<SelectTrigger><SelectValue placeholder="Choose an environment" /></SelectTrigger>
<SelectContent>
<SelectItem v-for="item in environments" :key="item.id" :value="item.id">
<strong>{{ item.label }}</strong>
<small>{{ item.detail }}</small>
<SelectItemIndicator>✓</SelectItemIndicator>
</SelectItem>
</SelectContent>
</SelectRoot>
</template>Floating positioning
This component uses the shared positioning engine. Use the live positioning example to change side, align, offsets, collision boundaries, strategy, and tracking while inspecting the resolved placement.
API
Vue package: @sectile/vue/select
SelectRootSelectTriggerSelectValueSelectContentSelectItemSelectItemIndicatorSelectViewportSelectItemTextSelectPortal
Props
SelectRootProps
alignAlignment of positioned content relative to its anchor.
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
avoidCollisionsWhether positioned content may flip or shift to remain visible.
collisionBoundaryBoundary used to keep positioned content visible.
collisionPaddingSpace kept between positioned content and its collision boundary.
defaultOpenInitial uncontrolled open state.
defaultValueInitial value used when the component owns its state.
disabledWhether interaction is unavailable.
disabledItemsItem values excluded from focus and selection.
formID of the native form associated with the control.
hideWhenDetachedWhether positioned content hides when its anchor leaves the layout.
itemsOrdered item values managed by the component.
labelAccessible name announced for the control.
modelValueCurrent value when state is controlled by the parent.
nameName used for native form submission.
openWhether the associated popup or disclosure is open.
policiesBehavior policies that customize validation, movement, or selection.
positionWhether the popup is positioned relative to its trigger.
readonlyWhether the value can be inspected but not changed.
requiredWhether the control must contain a valid value before submission.
sidePreferred side of the anchor for positioned content.
sideOffsetDistance between positioned content and its anchor.
strategyCSS positioning strategy used for anchored content.
textValueReturns searchable or presentational text for an item value.
trackingUpdate strategy used while anchored content is open.
typeaheadTimeoutMsIdle time in milliseconds before the printable-text search buffer resets.
unmountOnExitWhether presence-managed content is removed from the DOM after its exit motion completes.
SelectItemProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
disabledWhether interaction is unavailable.
valueCurrent value exposed by this contract.
SelectPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
SelectPortalProps
deferWhether Teleport target resolution waits until the end of the current mount or update tick.
disabledWhether interaction is unavailable.
toTeleport target for portalled content.
Slots
SelectRootSlotProps
disabledWhether interaction is unavailable.
highlightedValueValue currently highlighted for interaction.
openWhether the associated popup or disclosure is open.
readonlyWhether the value can be inspected but not changed.
valueCurrent value exposed by this contract.
SelectItemSlotProps
disabledWhether interaction is unavailable.
highlightedWhether this item is highlighted for interaction.
selectedWhether this item is selected.
valueCurrent value exposed by this contract.
Events
SelectRoot
highlightEmitted when the highlighted item changes.
update:modelValueEmitted when the component requests a new controlled value.
update:openEmitted when the component requests a new open state.
Other types
SelectTextValueResolver
type SelectTextValueResolver = NonNullable<SelectRootProps['textValue']>SelectValueChangeHandler
type SelectValueChangeHandler = (value: string | null) => voidSelectOpenChangeHandler
type SelectOpenChangeHandler = (value: boolean) => voidSelectHighlightHandler
type SelectHighlightHandler = (value: string | null) => voidParts
Shared scope: [data-scope="select"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
root | [data-part="root"] | Defines the component boundary and owns its composed parts. | — |
trigger | [data-part="trigger"] | Opens, closes, or activates the associated content. | — |
value | [data-part="value"] | Displays the current committed value. | — |
content | [data-part="content"] | Contains the component content shown for the active state. | — |
viewport | [data-part="viewport"] | Clips and positions the currently visible content. | — |
item | [data-part="item"] | Represents one selectable or actionable item. | — |
item-text | [data-part="item-text"] | Renders the item label independently from its controls. | — |
item-indicator | [data-part="item-indicator"] | Shows the item selection state. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Arrow keys | Move the active option in the visible orientation. |
| Home / End | Move to the first or last eligible option. |
| Enter / Space | Select or activate the current option. |
| Printable text | Move to the next matching option when typeahead is available. |
Accessibility
The trigger owns a portalled listbox whose active descendant, selected options, and disabled options remain linked across DOM boundaries.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
