Select
A neo-brutalist style dropdown select built on top of reka-ui's Select primitive, with full sub-component support.
Demo
Installation
pnpm dlx brutx-vue@latest add selectUsage
<script setup>
import { Select, SelectTrigger, SelectContent, SelectItem, SelectLabel } from 'brutx-ui-vue'
import { SelectGroup, SelectValue } from 'reka-ui'
</script>
<template>
<Select>
<SelectTrigger class="w-[280px]">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="orange">Orange</SelectItem>
<SelectItem value="grape">Grape</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</template>Custom Slot Composition and Attribute Binding
The default slot replaces the full selector and does not provide scoped slot arguments. When composing atomic controls, pass form name, required, and disabled to Select; bind the trigger id and disabled state directly in the slot content.
<script setup>
import { ref } from 'vue'
import { Select, SelectTrigger, SelectContent, SelectItem } from 'brutx-ui-vue'
import { SelectValue } from 'reka-ui'
const isDisabled = ref(false)
</script>
<template>
<Select name="fruit" required :disabled="isDisabled">
<SelectTrigger id="fruit-select" :disabled="isDisabled" class="w-[280px]">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
</SelectContent>
</Select>
</template>Unified Usage
In addition to using individual atomic components, you can use the pre-packaged unified Select component, which supports passing an options array and automatically grouping items.
<script setup>
import { ref } from 'vue'
import { Select } from 'brutx-ui-vue'
const selectedValue = ref('')
const foodOptions = [
{ label: 'Apple', value: 'apple', category: 'fruits', categoryName: 'Fruits' },
{ label: 'Banana', value: 'banana', category: 'fruits', categoryName: 'Fruits' },
{ label: 'Carrot', value: 'carrot', category: 'vegetables', categoryName: 'Vegetables' },
{ label: 'Potato', value: 'potato', category: 'vegetables', categoryName: 'Vegetables' },
{ label: 'Milk', value: 'milk' } // ungrouped
]
</script>
<template>
<!-- Basic Usage -->
<Select
v-model="selectedValue"
:options="foodOptions"
placeholder="Select your food"
class="w-[280px]"
/>
<!-- Auto Grouping Usage -->
<Select
v-model="selectedValue"
:options="foodOptions"
group-field="category"
group-label="categoryName"
placeholder="Select food (Grouped)"
class="w-[280px]"
/>
</template>Using v-model
<script setup>
import { ref } from 'vue'
import {
Select,
SelectTrigger,
SelectContent,
SelectItem,
} from 'brutx-ui-vue'
import { SelectValue } from 'reka-ui'
const selectedFruit = ref('')
</script>
<template>
<Select v-model="selectedFruit">
<SelectTrigger class="w-[280px]">
<SelectValue placeholder="Select a fruit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="orange">Orange</SelectItem>
</SelectContent>
</Select>
</template>Sub-components
| Component | Description |
|---|---|
Select | Unified selector with an options data source and slot composition, built on Reka UI primitives |
SelectRoot | Reka UI root primitive that provides context for atomic composition (import from reka-ui) |
SelectValue | Reka UI primitive that displays the selected value or placeholder (import from reka-ui) |
SelectGroup | Reka UI primitive that groups options (import from reka-ui) |
SelectTrigger | Button that opens the dropdown |
SelectContent | Dropdown content panel |
SelectItem | Selectable option |
SelectLabel | Group label |
SelectSeparator | Visual separator |
SelectScrollUpButton | Scroll up indicator |
SelectScrollDownButton | Scroll down indicator |
API Reference
Select
| Name | Type | Default | Description |
|---|---|---|---|
options | SelectOption[] | undefined | [] | The unified select option list. Each option has a label and non-empty value, may be disabled, and can include custom fields used for grouping. |
DetailsDeclared typeSelectOption[] | undefined Referenced types SelectOption Type definition — SelectOptionexport interface SelectOption {
label: string
value: string
disabled?: boolean
[key: string]: unknown
}Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
groupField | string | undefined | undefined | The option field used to group items. When omitted, options are displayed as a flat list. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
groupLabel | string | undefined | undefined | The field on the first option of each group used as its heading; when omitted or absent, the groupField value is used. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
placeholder | string | undefined | undefined | Placeholder text shown before an option is selected; when omitted, the localized select.placeholder message is used. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
disabled | boolean | undefined | false | Disables the select root state and its built-in trigger. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
required | boolean | undefined | false | Marks the select as required; the unified trigger hides its clear action while required is true. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
name | string | undefined | undefined | The form field name passed to SelectRoot. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
id | string | undefined | undefined | The DOM ID for the built-in trigger. With a custom trigger slot, the slot content supplies its own ID. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
size | "default" | "lg" | "sm" | undefined | "default" | The size variant of the built-in trigger. |
DetailsDeclared type"default" | "lg" | "sm" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
variant | "default" | "success" | "error" | undefined | "default" | The border and state variant of the built-in trigger. |
DetailsDeclared type"default" | "success" | "error" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
errorMessage | string | undefined | undefined | The error message passed to the built-in trigger for its error-state semantics. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
clearable | boolean | undefined | false | Allows the built-in trigger to show a clear action when a value is selected; the action is disabled when required is true. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
position | "popper" | "item-aligned" | undefined | "popper" | Sets how the options panel is positioned relative to the trigger. |
DetailsDeclared type"popper" | "item-aligned" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
class | string | undefined | — | Custom CSS classes merged onto the built-in trigger together with triggerClass. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
triggerClass | string | undefined | undefined | Custom CSS classes added to the built-in trigger. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
contentClass | string | undefined | undefined | Custom CSS classes added to the options panel. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
itemVariant | "default" | "primary" | "secondary" | undefined | "default" | The variant applied to each SelectItem generated from options. |
DetailsDeclared type"default" | "primary" | "secondary" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/types.ts | |||
modelValue | string | undefined | — | The currently selected string value, controlled with v-model; it may be undefined when nothing is selected. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/Select.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@update:modelValue | [value: string | undefined] | Emits the new value when the selection changes; the built-in clear action emits undefined. |
DetailsDeclared type[value: string | undefined] Sourcepackages/ui/src/components/select/Select.vue | ||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | Replaces the entire Select content. When provided, the component renders neither its built-in trigger nor the options panel, so the slot must compose the primitives itself. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/Select.vue | ||
#trigger | {} | Replaces the built-in trigger while the options panel is still generated from options. The slot receives no arguments. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/Select.vue | ||
SelectContent
| Name | Type | Default | Description |
|---|---|---|---|
position | "popper" | "item-aligned" | undefined | "popper" | Controls how the content panel is positioned relative to its trigger. |
DetailsDeclared type"popper" | "item-aligned" | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectContent.vue | |||
class | string | undefined | undefined | Custom CSS classes added to the floating content panel. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectContent.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | Renders options, groups, and other content-panel children. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/SelectContent.vue | ||
SelectItem
| Name | Type | Default | Description |
|---|---|---|---|
valueRequired | string | — | The non-empty, unique string value of this option, used as the selection result. |
DetailsDeclared typestring Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
disabled | boolean | undefined | false | Prevents the user from selecting this option. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
variant | "default" | "primary" | "secondary" | undefined | "default" | The visual variant for this option. |
DetailsDeclared typeNonNullable<"default" | "primary" | "secondary" | null | undefined> | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
class | string | undefined | undefined | Custom CSS classes added to the option root element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
indicatorClass | string | undefined | undefined | Custom CSS classes added to the selected-state indicator. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
iconClass | string | undefined | undefined | Custom CSS classes added to the selected check icon. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
iconSize | IconSize | undefined | "md" | Sets the size of the selected check icon. |
DetailsDeclared typeIconSize | undefined Literal values
Referenced types IconSize Type definition — IconSizeexport type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']> Default value details
Sourcepackages/ui/src/components/select/SelectItem.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The content displayed in the option text area. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/SelectItem.vue | ||
SelectLabel
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | — | Custom CSS classes added to the group heading element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectLabel.vue | |||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The group heading text or other heading content. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/SelectLabel.vue | ||
SelectScrollDownButton
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | undefined | Custom CSS classes added to the scroll-down indicator control. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectScrollDownButton.vue | |||
iconSize | IconSize | undefined | "md" | Sets the size of the scroll-down arrow icon. |
DetailsDeclared typeIconSize | undefined Literal values
Referenced types IconSize Type definition — IconSizeexport type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']> Default value details
Sourcepackages/ui/src/components/select/SelectScrollDownButton.vue | |||
SelectScrollUpButton
| Name | Type | Default | Description |
|---|---|---|---|
class | string | undefined | undefined | Custom CSS classes added to the scroll-up indicator control. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectScrollUpButton.vue | |||
iconSize | IconSize | undefined | "md" | Sets the size of the scroll-up arrow icon. |
DetailsDeclared typeIconSize | undefined Literal values
Referenced types IconSize Type definition — IconSizeexport type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']> Default value details
Sourcepackages/ui/src/components/select/SelectScrollUpButton.vue | |||
SelectSeparator
| Name | Type | Default | Description |
|---|---|---|---|
decorative | boolean | undefined | true | Declares whether the separator is decorative; the primitive hides decorative separators from the accessibility tree. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectSeparator.vue | |||
class | string | undefined | undefined | Custom CSS classes added to the separator element. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectSeparator.vue | |||
SelectTrigger
| Name | Type | Default | Description |
|---|---|---|---|
size | "default" | "lg" | "sm" | undefined | "default" | The trigger size variant, which also determines the mapped dropdown icon size. |
DetailsDeclared typeNonNullable<"default" | "lg" | "sm" | null | undefined> | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
variant | "default" | "error" | "success" | undefined | "default" | The trigger border and state variant. |
DetailsDeclared typeNonNullable<"default" | "success" | "error" | null | undefined> | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
errorMessage | string | undefined | undefined | The error-state message associated with the trigger when it is invalid. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
disabled | boolean | undefined | false | Disables the trigger and its clear action. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
id | string | undefined | undefined | The DOM ID of the native trigger button. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
clearable | boolean | undefined | false | Allows the clear button to appear when a value is selected and the trigger is enabled. |
DetailsDeclared typeboolean | undefined Literal values
Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
modelValue | unknown | undefined | The current value, used to determine whether there is a selection to clear. |
DetailsDeclared typeunknown Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
class | string | undefined | undefined | Custom CSS classes added to the trigger button. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
iconClass | string | undefined | undefined | Custom CSS classes added to the dropdown indicator icon. |
DetailsDeclared typestring | undefined Default value details
Sourcepackages/ui/src/components/select/SelectTrigger.vue | |||
| Name | Signature or type | Description |
|---|---|---|
@clear | [] | Emitted when the user activates the clear action; the event carries no payload. |
DetailsDeclared type[] Sourcepackages/ui/src/components/select/SelectTrigger.vue | ||
| Name | Signature or type | Description |
|---|---|---|
#default | {} | The trigger content, usually including SelectValue. |
DetailsDeclared type{}Sourcepackages/ui/src/components/select/SelectTrigger.vue | ||
Reka UI Primitives
The unified Select props, events, and slots are listed above. When composing atomic controls, headless primitives such as SelectRoot and SelectValue come from reka-ui and should be imported from reka-ui; their remaining prop and slot contracts are defined by Reka UI.
Accessibility
- Keyboard: Supports
Space/Enterto open the dropdown,Escapeto close, and arrow keys to navigate options - ARIA Attributes: Automatically manages
aria-expanded,aria-haspopup,aria-activedescendant, etc. - Focus Management: Focus is trapped within the dropdown when open; focus returns to the trigger when closed