Select
Lets users select one option from a list. Ideal for forms, settings, or any interface where a single choice is required.
Example
Custom Option Layout
Use #item-prefix and #item-label to tailor the standard row — for example, an avatar plus a two-line label with a secondary description. #prefix on the trigger reuses the selected option's accessory.
States
Trigger Slots
Label, Description, Error
Select supports label, description, error, and required directly — no FormControl wrapper needed. The error suppresses the description and wires aria-invalid + aria-errormessage onto the trigger.
Notes
- Prefer
#item-prefix,#item-label, and#item-suffixwhen you want to customize the standard option row. - Use
v-model:openwhen you need to control the menu state. - By default,
Selectsizes itself to fit its option content. Setclass="w-full"when you want a full-width trigger. Selectaccepts flat options only. Empty and nullish options are omitted.
API Reference
Show types
import type { Component } from 'vue'
import type { InputLabelingProps } from '../../composables/useInputLabeling'
export type SelectOptionValue = string | number | bigint | Record<string, any>
export type SelectOption =
| string
| {
label: string
value: SelectOptionValue
disabled?: boolean
icon?: string | Component
description?: string
slot?: string
[key: string]: any
}
export type SelectNormalizedOption = Exclude<SelectOption, string>
export interface SelectProps extends InputLabelingProps {
/** Size of the select input. */
size?: 'sm' | 'md' | 'lg' | 'xl'
/** Visual style of the select input. */
variant?: 'subtle' | 'outline' | 'ghost'
/** Placeholder text displayed when no option is selected. */
placeholder?: string
/** If true, disables the select input. */
disabled?: boolean
/** The currently selected value. */
modelValue?: SelectOptionValue
/** Controls the visibility of the select menu. */
open?: boolean
/** Options to display in the dropdown. */
options?: SelectOption[]
/** Fallback empty-state copy rendered when no options are available. */
emptyText?: string
}
export interface SelectTriggerSlotProps {
/** Whether the select menu is currently open. */
open: boolean
/** Whether the trigger is disabled. */
disabled: boolean
/** Currently selected option, if any. */
selectedOption: SelectNormalizedOption | null
/** Plain-text label shown in the trigger. */
displayValue: string
}
export interface SelectItemSlotProps {
/** Option currently being rendered. */
option: SelectNormalizedOption
}
export interface SelectSlots {
/** Fully custom trigger renderer. */
trigger?: (props: SelectTriggerSlotProps) => any
/** Overrides the rendered label content. Receives `{ required }`. */
label?: (props: { required: boolean }) => any
/** Overrides the rendered description content. */
description?: () => any
/** Content rendered before the trigger value. */
prefix?: () => any
/** Content rendered after the trigger value. */
suffix?: () => any
/**
* Shared renderer for option labels.
* @deprecated use `#item-label` for per-row label customization. `#option` remains as a back-compat alias through v1.x.
*/
option?: (props: SelectItemSlotProps) => any
/** Content rendered before the standard option label. */
'item-prefix'?: (props: SelectItemSlotProps) => any
/** Content rendered for the standard option label area. */
'item-label'?: (props: SelectItemSlotProps) => any
/** Content rendered after the standard option label. */
'item-suffix'?: (props: SelectItemSlotProps) => any
/** Fallback content rendered when no options are available. */
empty?: () => any
/** Content rendered below the option list. */
footer?: () => any
[slotName: string]: ((props: any) => any) | undefined
}
export interface SelectEmits {
/** Fired when the selected value changes. */
'update:modelValue': [value: SelectOptionValue | undefined]
/** Fired when the open state changes. */
'update:open': [value: boolean]
}
export interface SelectExposed {}| Prop | Default | Type |
|---|---|---|
size | "sm" | "md" | "sm" | "lg" | "xl" Size of the select input. |
variant | "subtle" | "subtle" | "outline" | "ghost" Visual style of the select input. |
placeholder | "Select option" | string Placeholder text displayed when no option is selected. |
disabled | — | boolean If true, disables the select input. |
modelValue | — | SelectOptionValue The currently selected value. |
open | false | boolean Controls the visibility of the select menu. |
options | [] | SelectOption[] Options to display in the dropdown. |
emptyText | "No options" | string Fallback empty-state copy rendered when no options are available. |
label | — | string Label rendered above (or beside, for binary controls) the input. |
description | — | string Helper text rendered below the input. Hidden when `error` is set. |
error | — | string | FrappeUIError Error message rendered below the input. When set, the control receives `aria-invalid="true"` and `data-state="invalid"`. May be either a string or an `Error` object whose `messages?: string[]` is rendered as stacked lines (with `Error.message` as the fallback). |
required | — | boolean Marks the field as required. Renders an asterisk next to the label and forwards `required` / `aria-required` to the underlying control. |
id | — | string HTML id of the underlying control. Auto-generated via `useId()` if omitted. |
| Slot | Payload |
|---|---|
trigger | SelectTriggerSlotProps Fully custom trigger renderer. |
label | { required: boolean; } Overrides the rendered label content. Receives `{ required }`. |
description | — Overrides the rendered description content. |
prefix | — Content rendered before the trigger value. |
suffix | — Content rendered after the trigger value. |
option | Deprecated — use `#item-label` for per-row label customization. `#option` remains as a back-compat alias through v1.x. |
item-prefix | SelectItemSlotProps Content rendered before the standard option label. |
item-label | SelectItemSlotProps Content rendered for the standard option label area. |
item-suffix | SelectItemSlotProps Content rendered after the standard option label. |
empty | — Fallback content rendered when no options are available. |
footer | — Content rendered below the option list. |
| Event | Payload |
|---|---|
update:modelValue | [value: SelectOptionValue | undefined] Fired when the model value changes. |
update:open | [value: boolean] Fired when the open state changes. |