- Accordion
- Alert
- Alert Dialog
- Autocomplete
- Auth Surface
- Avatar
- Badge
- Browse Catalog Dialog
- Button
- Card
- Checkbox
- Checkbox Group
- Collapsible
- Combobox
- Command
- Connector Setup Dialog
- Cookie Banner
- Dialog
- Directory Card
- Directory Detail
- Directory Skeleton
- DrawerНовое
- Token Parts Input
- Empty
- Field
- Fieldset
- File Preview Modal
- File Preview Skeleton
- Form
- Frame
- Group
- Icon
- Input
- Input Group
- Kbd
- Label
- Legal Shell
- Menu
- Mermaid Diagram
- Mind Map Diagram
- Not Found Screen
- Onboarding Frame
- Popover
- PDF Thumbnail
- Personalization Landing
- Preview Card
- Pricing Page
- Progress
- Radio Group
- Ring Spinner
- Scroll Area
- Select
- Separator
- Settings Page
- Settings Skills
- Settings Connectors
- Settings Capabilities
- Settings Usage
- Settings Account
- Settings Billing
- Sheet
- Sidebar
- Skeleton
- Skill Create Dialog
- Slider
- Spinner
- Stat
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Tooltip
- Компоненты AI
- Chat Conversation
- Chat Message
- Chat Response
- Chat Suggestion
- Chat Prompt Input
- Slash Highlighted Textarea
- Chat Search Dialog
- Chat Skill Doc
- Chat Connector Detail
- Chat Attachments
- Chat File Card
- Chat Token Chip
- Chat Code Block
- Chat Image
- Chat Inline Citation
- Chat Sources
- Chat Web Search
- Chat Research
- Chat Source
- Chat Actions
- Chat Context
- Chat Loader
- Chat Compaction
- Chat Timeline
- Chat Snippet
- Chat Terminal
- Chat Stack Trace
- Chat Test Results
- Chat File Tree
- Chat Environment Variables
- Chat Audio Player
- Chat Transcription
- Chat Speech Input
- Chat Mic Selector
- Chat Voice Selector
- Chat Agent
- Chat Persona
- Chat Connection
- Chat Connector Suggestion
- Chat Queue
- Chat Checkpoint
- Chat Confirmation
- Chat Artifact
- Chat JSX Preview
- Chat Schema Display
- Chat Package Info
- Chat Commit
- Chat Plan
- Chat Open In Chat
- Chat Sandbox
- Chat Model Selector
- Chat Canvas
- Chat Node
- Chat Edge
Select
Распространённый компонент формы для выбора заранее заданного значения из выпадающего меню.
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" defaultValue="next" items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Установка
pnpm dlx shadcn@latest add @oracul/select
Использование
import {
Select,
SelectItem,
SelectPopup,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"const items = [
{ label: "Select framework", value: null },
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
]
<Select items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
<SelectLabel>Frameworks</SelectLabel>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
{item.label}
</SelectItem>
))}
</SelectPopup>
</Select>API
Select
Корневой компонент. Псевдоним для Select.Root из Base UI.
SelectTrigger
Кнопка-триггер, открывающая выпадающий список. Стилизованная обёртка для Select.Trigger из Base UI.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Управляет размером триггера |
SelectValue
Отображает выбранное значение. Стилизованная обёртка для Select.Value из Base UI.
SelectPopup
Контейнер всплывающего окна с вариантами выбора. Также экспортируется как SelectContent.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
alignItemWithTrigger | boolean | true | Выравнивает выбранный элемент по триггеру |
sideOffset | number | 4 | Расстояние от триггера в пикселях |
SelectItem
Отдельный вариант выбора. Стилизованная обёртка для Select.Item из Base UI со встроенным индикатором.
SelectGroup
Группирует связанные элементы списка. Псевдоним для Select.Group из Base UI.
SelectLabel
Подпись для всех вариантов во всплывающем окне. Стилизованная обёртка для Select.Label из Base UI. Клик по ней переводит фокус на триггер списка, не открывая всплывающее окно.
SelectGroupLabel
Подпись для группы вариантов выбора. Стилизованная обёртка для Select.GroupLabel из Base UI.
SelectSeparator
Визуальный разделитель между элементами. Стилизованная обёртка для Select.Separator из Base UI.
SelectButton
Самостоятельная кнопка, стилизованная как SelectTrigger. Используйте её в свойстве render других компонентов-триггеров (например, ComboboxTrigger, MenuTrigger), чтобы придать им вид списка выбора.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Управляет размером кнопки |
import { SelectButton } from "@/components/ui/select"<ComboboxTrigger render={<SelectButton />}>
<ComboboxValue placeholder="Select a fruit" />
</ComboboxTrigger>Примеры
Для доступной разметки подписей и валидации предпочтительно оборачивать списки выбора в компонент Field. Смотрите соответствующий пример: Поле выбора.
Малый размер
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" items={items}>
<SelectTrigger size="sm">
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Большой размер
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" items={items}>
<SelectTrigger size="lg">
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Отключённый
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" items={items}>
<SelectTrigger disabled>
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Без выравнивания элемента
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" items={items}>
<SelectTrigger>
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
С группами
import {
Select,
SelectGroup,
SelectGroupLabel,
SelectItem,
SelectPopup,
SelectSeparator,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const frontend = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
const backend = [
{ label: "Express", value: "express" },
{ label: "NestJS", value: "nestjs" },
{ label: "Fastify", value: "fastify" },
{ label: "Django", value: "django" },
{ label: "Flask", value: "flask" },
{ label: "Rails", value: "rails" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фреймворк" items={[...frontend, ...backend]}>
<SelectTrigger>
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup>
<SelectGroup>
<SelectGroupLabel>Фронтенд</SelectGroupLabel>
{frontend.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectGroup>
<SelectSeparator />
<SelectGroup>
<SelectGroupLabel>Бэкенд</SelectGroupLabel>
{backend.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectGroup>
</SelectPopup>
</Select>
);
}
С подписью
import {
Select,
SelectItem,
SelectLabel,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Яблоко", value: "apple" },
{ label: "Банан", value: "banana" },
{ label: "Апельсин", value: "orange" },
];
export default function Particle() {
return (
<Select aria-label="Выберите фрукт" defaultValue={items[0]} items={items}>
<SelectLabel>Фрукты</SelectLabel>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
{item.label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Множественный выбор
"use client";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const languages = {
cpp: "C++",
csharp: "C#",
go: "Go",
java: "Java",
javascript: "JavaScript",
php: "PHP",
python: "Python",
rust: "Rust",
swift: "Swift",
typescript: "TypeScript",
};
type Language = keyof typeof languages;
const values = Object.keys(languages) as Language[];
function renderValue(value: Language[]) {
if (value.length === 0) {
return "Выберите языки…";
}
const firstLanguage = value[0] ? languages[value[0]] : "";
const additionalLanguages =
value.length > 1 ? ` (ещё +${value.length - 1})` : "";
return firstLanguage + additionalLanguages;
}
export default function Particle() {
return (
<Select
aria-label="Выберите языки"
defaultValue={["javascript", "typescript"]}
multiple
>
<SelectTrigger>
<SelectValue>{renderValue}</SelectValue>
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{values.map((value) => (
<SelectItem key={value} value={value}>
{languages[value]}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
С иконкой
import { IconPlug } from "@tabler/icons-react";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
return (
<Select
aria-label="Выберите фреймворк с иконкой"
defaultValue="next"
items={items}
>
<SelectTrigger>
<IconPlug aria-hidden="true" stroke={1.5} />
<SelectValue />
</SelectTrigger>
<SelectPopup alignItemWithTrigger={false}>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Варианты с иконками
"use client";
import { IconBolt, IconCode, IconStack, IconWorld } from "@tabler/icons-react";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ icon: IconStack, label: "Компоненты", value: "components" },
{ icon: IconBolt, label: "Производительность", value: "performance" },
{ icon: IconWorld, label: "Сеть", value: "network" },
{ icon: IconCode, label: "Разработка", value: "development" },
];
export default function Particle() {
return (
<Select
aria-label="Выберите категорию"
defaultValue={items[0]}
itemToStringValue={(item) => item.value}
>
<SelectTrigger>
<SelectValue>
{(item) => (
<span className="flex items-center gap-2">
<item.icon stroke={1.5} />
<span className="truncate">{item.label}</span>
</span>
)}
</SelectValue>
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
<span className="flex items-center gap-2">
<item.icon stroke={1.5} />
<span className="truncate">{item.label}</span>
</span>
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
Со значениями-объектами
"use client";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ description: "npx create-next-app", label: "Next.js", value: "next" },
{ description: "npm create vite@latest", label: "Vite", value: "vite" },
{ description: "npm create astro@latest", label: "Astro", value: "astro" },
{ description: "npx create-remix", label: "Remix", value: "remix" },
];
export default function Particle() {
return (
<Select
aria-label="Выберите фреймворк с командой"
defaultValue={items[0]}
itemToStringValue={(item) => item.value}
>
<SelectTrigger className="py-1">
<SelectValue>
{(item) => (
<span className="flex flex-col">
<span className="truncate">{item.label}</span>
<span className="truncate text-muted-foreground text-xs">
{item.description}
</span>
</span>
)}
</SelectValue>
</SelectTrigger>
<SelectPopup>
{items.map((item) => (
<SelectItem key={item.value} value={item}>
<span className="flex flex-col">
<span className="truncate">{item.label}</span>
<span className="truncate text-muted-foreground text-xs">
{item.description}
</span>
</span>
</SelectItem>
))}
</SelectPopup>
</Select>
);
}
SelectButton с Combobox
Используйте SelectButton в свойстве render компонента ComboboxTrigger, чтобы создать combobox, выглядящий как список выбора.
"use client";
import { IconSearch } from "@tabler/icons-react";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxTrigger,
ComboboxValue,
} from "@/components/ui/combobox";
import { SelectButton } from "@/components/ui/select";
const items = [
{ label: "Яблоко", value: "apple" },
{ label: "Банан", value: "banana" },
{ label: "Апельсин", value: "orange" },
{ label: "Виноград", value: "grape" },
{ label: "Клубника", value: "strawberry" },
{ label: "Манго", value: "mango" },
{ label: "Ананас", value: "pineapple" },
{ label: "Киви", value: "kiwi" },
{ label: "Персик", value: "peach" },
{ label: "Груша", value: "pear" },
];
export default function Particle() {
return (
<Combobox items={items}>
<ComboboxTrigger render={<SelectButton />}>
<ComboboxValue placeholder="Выберите фрукт" />
</ComboboxTrigger>
<ComboboxPopup aria-label="Выберите фрукт">
<div className="border-b p-2">
<ComboboxInput
className="rounded-md before:rounded-[calc(var(--radius-md)-1px)]"
placeholder="Поиск фруктов..."
showTrigger={false}
startAddon={<IconSearch stroke={1.5} />}
/>
</div>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Интеграция с формой
"use client";
import type { FormEvent } from "react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
} from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Next.js", value: "next" },
{ label: "Vite", value: "vite" },
{ label: "Astro", value: "astro" },
];
export default function Particle() {
const [loading, setLoading] = useState(false);
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
setLoading(true);
await new Promise((r) => setTimeout(r, 800));
setLoading(false);
alert(`Фреймворк: ${formData.get("framework") || ""}`);
};
return (
<Form className="flex w-full max-w-64 flex-col gap-4" onSubmit={onSubmit}>
<Field>
<FieldLabel>Фреймворк</FieldLabel>
<Select
aria-label="Выберите фреймворк"
items={items}
name="framework"
required
>
<SelectTrigger>
<SelectValue placeholder="Выберите фреймворк" />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
<FieldDescription>Выберите любимый.</FieldDescription>
<FieldError>Пожалуйста, выберите значение.</FieldError>
</Field>
<Button loading={loading} type="submit">
Отправить
</Button>
</Form>
);
}
На этой странице