YA Select
A dropdown select component for choosing from a list of options, built on Radix UI primitives
The YaSelect is a dropdown select component in the YaVendio Design System. Built on Radix UI Select primitives, it provides full keyboard navigation, accessibility, and custom styling with portal-based positioning.
Quick Start
pnpm dlx shadcn@latest add @yavendio/ya-selectnpx shadcn@latest add @yavendio/ya-selectyarn dlx shadcn@latest add @yavendio/ya-selectimport {
YaSelect,
YaSelectTrigger,
YaSelectValue,
YaSelectContent,
YaSelectItem,
} from '@/components/ui/ya-select'
export default function Example() {
return (
<YaSelect>
<YaSelectTrigger>
<YaSelectValue placeholder="Select an option..." />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectItem value="option1">Option 1</YaSelectItem>
<YaSelectItem value="option2">Option 2</YaSelectItem>
<YaSelectItem value="option3">Option 3</YaSelectItem>
</YaSelectContent>
</YaSelect>
)
}Basic Select
Sizes
Two sizes for different use cases.
| Size | Height | Usage |
|---|---|---|
md | 40px | Most use cases, default |
sm | 32px | Compact UIs, tables, toolbars |
<YaSelect>
<YaSelectTrigger size="md">
<YaSelectValue placeholder="Medium size" />
</YaSelectTrigger>
<YaSelectContent>...</YaSelectContent>
</YaSelect>
<YaSelect>
<YaSelectTrigger size="sm">
<YaSelectValue placeholder="Small size" />
</YaSelectTrigger>
<YaSelectContent>...</YaSelectContent>
</YaSelect>With Groups and Labels
Use groups to organize options logically.
import {
YaSelect,
YaSelectTrigger,
YaSelectValue,
YaSelectContent,
YaSelectItem,
YaSelectGroup,
YaSelectLabel,
YaSelectSeparator,
} from '@/components/ui/ya-select'
<YaSelect>
<YaSelectTrigger>
<YaSelectValue placeholder="Choose..." />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectGroup>
<YaSelectLabel>Fruits</YaSelectLabel>
<YaSelectItem value="apple">Apple</YaSelectItem>
<YaSelectItem value="banana">Banana</YaSelectItem>
</YaSelectGroup>
<YaSelectSeparator />
<YaSelectGroup>
<YaSelectLabel>Vegetables</YaSelectLabel>
<YaSelectItem value="carrot">Carrot</YaSelectItem>
<YaSelectItem value="broccoli">Broccoli</YaSelectItem>
</YaSelectGroup>
</YaSelectContent>
</YaSelect>States
Please select a valid priority
Disabled
<YaSelect disabled>
<YaSelectTrigger>
<YaSelectValue placeholder="Disabled select" />
</YaSelectTrigger>
<YaSelectContent>...</YaSelectContent>
</YaSelect>Features:
- Reduced opacity (50%)
- Non-interactive
Destructive
Use for validation errors.
Please select a valid category
<YaSelect>
<YaSelectTrigger destructive>
<YaSelectValue placeholder="Select a category" />
</YaSelectTrigger>
<YaSelectContent>...</YaSelectContent>
</YaSelect>Features:
- Red border
- Combine with error message for validation feedback
Controlled Component
Use value and onValueChange for controlled behavior.
Make a selection
import { useState } from 'react'
export default function ControlledExample() {
const [selected, setSelected] = useState('')
return (
<YaSelect value={selected} onValueChange={setSelected}>
<YaSelectTrigger>
<YaSelectValue placeholder="Select a framework" />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectItem value="react">React</YaSelectItem>
<YaSelectItem value="vue">Vue</YaSelectItem>
<YaSelectItem value="angular">Angular</YaSelectItem>
</YaSelectContent>
</YaSelect>
)
}Examples
Validation Example
import { useState } from 'react'
export default function ValidationExample() {
const [value, setValue] = useState('')
const [error, setError] = useState('')
const handleSubmit = () => {
if (!value) {
setError('Please select a priority level')
} else {
setError('')
}
}
return (
<div className="flex flex-col gap-4">
<YaSelect
value={value}
onValueChange={(val) => {
setValue(val)
setError('')
}}
>
<YaSelectTrigger destructive={!!error}>
<YaSelectValue placeholder="Select priority" />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectItem value="low">Low</YaSelectItem>
<YaSelectItem value="medium">Medium</YaSelectItem>
<YaSelectItem value="high">High</YaSelectItem>
</YaSelectContent>
</YaSelect>
{error && <p className="text-xs text-destructive">{error}</p>}
<YaButton onClick={handleSubmit}>Submit</YaButton>
</div>
)
}Form with Multiple Selects
Compact Selection Row
<div className="flex gap-4 items-end">
<YaSelect>
<YaSelectTrigger size="sm">
<YaSelectValue placeholder="Sort by" />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectItem value="date">Date</YaSelectItem>
<YaSelectItem value="name">Name</YaSelectItem>
</YaSelectContent>
</YaSelect>
<YaSelect>
<YaSelectTrigger size="sm">
<YaSelectValue placeholder="Order" />
</YaSelectTrigger>
<YaSelectContent>
<YaSelectItem value="asc">Ascending</YaSelectItem>
<YaSelectItem value="desc">Descending</YaSelectItem>
</YaSelectContent>
</YaSelect>
</div>Component API
YaSelect (Root)
The root component that provides context.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Controlled value |
defaultValue | string | - | Default value (uncontrolled) |
onValueChange | (value: string) => void | - | Callback when value changes |
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Callback when open state changes |
disabled | boolean | false | Disable the select |
required | boolean | false | Mark as required |
name | string | - | Name for form submission |
YaSelectTrigger
The button that opens the select dropdown.
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'md' | 'sm' | 'md' | Trigger size |
destructive | boolean | false | Apply error styling |
className | string | - | Additional classes |
YaSelectValue
Displays the selected value or placeholder.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | - | Placeholder text |
YaSelectContent
The dropdown content container. Uses Portal for positioning.
| Prop | Type | Default | Description |
|---|---|---|---|
position | 'popper' | 'item-aligned' | 'popper' | Positioning mode |
sideOffset | number | 4 | Distance from trigger |
className | string | - | Additional classes |
YaSelectItem
An individual option in the select.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | Item value |
disabled | boolean | false | Disable the item |
icon | ReactNode | - | Optional icon |
className | string | - | Additional classes |
YaSelectGroup
Groups related items together.
YaSelectLabel
Label for a group of items.
YaSelectSeparator
Visual separator between items or groups.
Accessibility
Best Practices
| Do | Don't |
|---|---|
| Use clear, concise labels for options | Use vague or unclear option labels |
| Order options logically | Random ordering of options |
| Include a descriptive placeholder | Skip the placeholder |
Use destructive prop for validation errors | Custom red styling without the prop |
Use sm size for dense interfaces | Force large selects in toolbars |
| Group related options with labels | Mix unrelated options without structure |
TypeScript
import {
YaSelect,
YaSelectTrigger,
YaSelectValue,
YaSelectContent,
YaSelectItem,
YaSelectGroup,
YaSelectLabel,
YaSelectSeparator,
} from '@/components/ui/ya-select'