- 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
Combobox
Поле ввода в сочетании со списком предопределённых элементов для выбора.
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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}>
<ComboboxInput
aria-label="Выберите элемент"
placeholder="Выберите элемент…"
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Установка
pnpm dlx shadcn@latest add @oracul/combobox
Использование
Одиночный выбор
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox"const items = [
{ value: "apple", label: "Apple" },
{ value: "banana", label: "Banana" },
{ value: "orange", label: "Orange" },
{ value: "grape", label: "Grape" },
]
<Combobox items={items}>
<ComboboxInput placeholder="Select an item..." />
<ComboboxPopup>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => <ComboboxItem key={item.value} value={item}>{item.label}</ComboboxItem>}
</ComboboxList>
</ComboboxPopup>
</Combobox>Множественный выбор
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxValue,
} from "@/components/ui/combobox"const items = [
{ value: "apple", label: "Apple" },
{ value: "banana", label: "Banana" },
{ value: "orange", label: "Orange" },
{ value: "grape", label: "Grape" },
]
<Combobox items={items} multiple>
<ComboboxChips>
<ComboboxValue>
{(value: { value: string; label: string }[]) => (
<>
{value?.map((item) => (
<ComboboxChip key={item.value} aria-label={item.value}>
{item.label}
</ComboboxChip>
))}
<ComboboxChipsInput
placeholder={value.length > 0 ? undefined : "Select an item..."}
aria-label="Select an item"
/>
</>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxPopup>
<ComboboxEmpty>No results found.</ComboboxEmpty>
<ComboboxList>
{(item) => <ComboboxItem value={item}>{item.label}</ComboboxItem>}
</ComboboxList>
</ComboboxPopup>
</Combobox>API
Combobox
Корневой компонент combobox. Управляет состоянием combobox и предоставляет контекст дочерним компонентам.
| Свойство | Тип | Описание |
|---|---|---|
items | readonly unknown[] | Массив элементов для отображения в combobox |
multiple | boolean | Разрешать ли множественный выбор |
open | boolean | Управляет тем, открыто ли всплывающее окно |
...props | React.ComponentProps<typeof Combobox> | Поддерживаются все свойства Base UI Combobox |
ComboboxInput
Компонент поля ввода для режима одиночного выбора с расширенными возможностями для вариантов размера и поддержки аддонов.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Вариант размера поля ввода |
startAddon | React.ReactNode | - | Элемент для отображения в начале (слева) поля ввода, например иконка |
showTrigger | boolean | true | Отображать ли кнопку-триггер (иконку шеврона) справа от поля ввода |
showClear | boolean | false | Отображать ли кнопку очистки (иконку X) справа от поля ввода при наличии значения |
triggerProps | Combobox.Trigger.Props | - | Свойства, передаваемые внутренней кнопке-триггеру; полезно для переопределения aria-label |
clearProps | Combobox.Clear.Props | - | Свойства, передаваемые внутренней кнопке очистки; полезно для переопределения aria-label |
className | string | - | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Input | - | Поддерживаются все стандартные атрибуты поля ввода combobox |
ComboboxPopup
Всплывающий контейнер, отображающий варианты combobox.
| Свойство | Тип | Описание |
|---|---|---|
className | string | Дополнительные CSS-классы для применения к компоненту |
portalProps | Combobox.Portal.Props | Свойства, передаваемые внутреннему порталу (keepMounted, container и т. д.); см. API портала Base UI Combobox |
...props | Свойства Base UI Combobox Popup | Поддерживаются все стандартные атрибуты всплывающего окна combobox |
ComboboxList
Прокручиваемый контейнер для элементов combobox.
| Свойство | Тип | Описание |
|---|---|---|
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox List | Поддерживаются все стандартные атрибуты списка combobox |
ComboboxItem
Отдельный выбираемый элемент combobox.
| Свойство | Тип | Описание |
|---|---|---|
value | unknown | Значение элемента |
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Item | Поддерживаются все стандартные атрибуты элемента combobox |
ComboboxEmpty
Отображает сообщение, когда результаты не найдены.
| Свойство | Тип | Описание |
|---|---|---|
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Empty | Поддерживаются все стандартные атрибуты пустого состояния combobox |
ComboboxGroup
Группирует связанные элементы combobox.
| Свойство | Тип | Описание |
|---|---|---|
items | readonly unknown[] | Массив элементов в этой группе |
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Group | Поддерживаются все стандартные атрибуты группы combobox |
ComboboxGroupLabel
Отображает подпись для группы combobox.
| Свойство | Тип | Описание |
|---|---|---|
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Group Label | Поддерживаются все стандартные атрибуты подписи группы combobox |
ComboboxCollection
Используется для обёртки элементов внутри группы при рендеринге.
| Свойство | Тип | Описание |
|---|---|---|
...props | Свойства Base UI Combobox Collection | Поддерживаются все стандартные атрибуты коллекции combobox |
ComboboxChips
Контейнер для отображения выбранных чипов в режиме множественного выбора.
| Свойство | Тип | Описание |
|---|---|---|
startAddon | React.ReactNode | Элемент для отображения в начале (слева) области чипов |
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | React.ComponentProps<'div'> | Поддерживаются все стандартные атрибуты div |
ComboboxChipsInput
Компонент поля ввода для использования внутри ComboboxChips в режиме множественного выбора. Это минимальное поле ввода без обёртки, триггера или кнопки очистки.
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
size | "sm" | "default" | "lg" | "default" | Вариант размера поля ввода |
className | string | - | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Input | - | Поддерживаются все стандартные атрибуты поля ввода combobox |
ComboboxChip
Отдельный чип, представляющий выбранный элемент в режиме множественного выбора.
| Свойство | Тип | Описание |
|---|---|---|
removeProps | Combobox.ChipRemove.Props | Свойства, передаваемые внутренней кнопке удаления; полезно для переопределения aria-label |
className | string | Дополнительные CSS-классы для применения к компоненту |
...props | Свойства Base UI Combobox Chip | Поддерживаются все стандартные атрибуты чипа combobox |
ComboboxValue
Предоставляет доступ к текущему значению для пользовательского рендеринга.
| Свойство | Тип | Описание |
|---|---|---|
...props | Свойства Base UI Combobox Value | Поддерживаются все стандартные атрибуты значения combobox |
Примеры
Отключённое состояние
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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 defaultValue={items[2]} disabled items={items}>
<ComboboxInput
aria-label="Выберите элемент"
placeholder="Выберите элемент…"
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Маленький размер
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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}>
<ComboboxInput
aria-label="Выберите вариант"
placeholder="Выберите вариант..."
size="sm"
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Большой размер
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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}>
<ComboboxInput
aria-label="Выберите вариант"
placeholder="Выберите вариант..."
size="lg"
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С подписью
"use client";
import { useId } from "react";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
import { Label } from "@/components/ui/label";
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() {
const id = useId();
return (
<Combobox items={items}>
<div className="flex flex-col items-start gap-2">
<Label htmlFor={id}>Фрукты</Label>
<ComboboxInput
aria-label="Выберите вариант"
id={id}
placeholder="Выберите вариант..."
/>
</div>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
Автоподсветка
Автоматически подсвечивать первый совпадающий вариант.
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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 autoHighlight items={items}>
<ComboboxInput
aria-label="Выберите вариант"
placeholder="Выберите вариант..."
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С кнопкой очистки
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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}>
<ComboboxInput
aria-label="Выберите вариант"
placeholder="Выберите вариант…"
showClear
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С группами
"use client";
import { Fragment } from "react";
import {
Combobox,
ComboboxCollection,
ComboboxEmpty,
ComboboxGroup,
ComboboxGroupLabel,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxSeparator,
} from "@/components/ui/combobox";
// Grouped items demo
type Tag = { id: string; label: string; group: "Status" | "Priority" | "Team" };
type TagGroup = { value: string; items: Tag[] };
const tagsData: Tag[] = [
// Status
{ group: "Status", id: "s-open", label: "Открыта" },
{ group: "Status", id: "s-in-progress", label: "В работе" },
{ group: "Status", id: "s-blocked", label: "Заблокирована" },
{ group: "Status", id: "s-resolved", label: "Решена" },
{ group: "Status", id: "s-closed", label: "Закрыта" },
// Priority
{ group: "Priority", id: "p-low", label: "Низкий" },
{ group: "Priority", id: "p-medium", label: "Средний" },
{ group: "Priority", id: "p-high", label: "Высокий" },
{ group: "Priority", id: "p-urgent", label: "Срочный" },
// Team
{ group: "Team", id: "t-design", label: "Дизайн" },
{ group: "Team", id: "t-frontend", label: "Фронтенд" },
{ group: "Team", id: "t-backend", label: "Бэкенд" },
{ group: "Team", id: "t-devops", label: "DevOps" },
{ group: "Team", id: "t-qa", label: "QA" },
{ group: "Team", id: "t-mobile", label: "Мобильная разработка" },
{ group: "Team", id: "t-data", label: "Данные" },
{ group: "Team", id: "t-security", label: "Безопасность" },
{ group: "Team", id: "t-platform", label: "Платформа" },
{ group: "Team", id: "t-infra", label: "Инфраструктура" },
{ group: "Team", id: "t-product", label: "Продукт" },
{ group: "Team", id: "t-marketing", label: "Маркетинг" },
{ group: "Team", id: "t-sales", label: "Продажи" },
{ group: "Team", id: "t-support", label: "Поддержка" },
{ group: "Team", id: "t-research", label: "Исследования" },
{ group: "Team", id: "t-content", label: "Контент" },
{ group: "Team", id: "t-analytics", label: "Аналитика" },
{ group: "Team", id: "t-operations", label: "Операции" },
{ group: "Team", id: "t-finance", label: "Финансы" },
{ group: "Team", id: "t-hr", label: "HR" },
{ group: "Team", id: "t-legal", label: "Юристы" },
{ group: "Team", id: "t-growth", label: "Рост" },
{ group: "Team", id: "t-partner", label: "Партнёрства" },
{ group: "Team", id: "t-community", label: "Сообщество" },
{ group: "Team", id: "t-docs", label: "Документация" },
{ group: "Team", id: "t-l10n", label: "Локализация" },
{ group: "Team", id: "t-a11y", label: "Доступность" },
{ group: "Team", id: "t-sre", label: "SRE" },
{ group: "Team", id: "t-release", label: "Релизы" },
{ group: "Team", id: "t-architecture", label: "Архитектура" },
{ group: "Team", id: "t-ux", label: "UX" },
{ group: "Team", id: "t-ui", label: "UI" },
{ group: "Team", id: "t-management", label: "Менеджмент" },
];
function groupTags(tags: Tag[]): TagGroup[] {
const groups: Record<string, Tag[]> = {};
for (const tag of tags) {
if (!groups[tag.group]) {
groups[tag.group] = [];
}
groups[tag.group]?.push(tag);
}
const order: Array<TagGroup["value"]> = ["Status", "Priority", "Team"];
return order.map((value) => ({ items: groups[value] ?? [], value }));
}
const groupedTags: TagGroup[] = groupTags(tagsData);
const groupLabels: Record<TagGroup["value"], string> = {
Priority: "Приоритет",
Status: "Статус",
Team: "Команда",
};
export default function Particle() {
return (
<Combobox items={groupedTags}>
<div className="flex flex-col items-start gap-2">
<ComboboxInput aria-label="Поиск тегов" placeholder="например, фича" />
</div>
<ComboboxPopup>
<ComboboxEmpty>Теги не найдены.</ComboboxEmpty>
<ComboboxList>
{(group: TagGroup) => (
<Fragment key={group.value}>
<ComboboxGroup items={group.items}>
<ComboboxGroupLabel>
{groupLabels[group.value]}
</ComboboxGroupLabel>
<ComboboxCollection>
{(tag: Tag) => (
<ComboboxItem key={tag.id} value={tag}>
{tag.label}
</ComboboxItem>
)}
</ComboboxCollection>
</ComboboxGroup>
{group.value !== "Team" && <ComboboxSeparator />}
</Fragment>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С множественным выбором
"use client";
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxValue,
} from "@/components/ui/combobox";
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 defaultValue={[items[0], items[4]]} items={items} multiple>
<ComboboxChips>
<ComboboxValue>
{(value: { value: string; label: string }[]) => (
<>
{value?.map((item) => (
<ComboboxChip aria-label={item.label} key={item.value}>
{item.label}
</ComboboxChip>
))}
<ComboboxChipsInput
aria-label="Выберите элемент"
placeholder={
value.length > 0 ? undefined : "Выберите элемент..."
}
/>
</>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С начальным аддоном
Отобразите иконку или другой элемент в начале поля ввода с помощью свойства startAddon.
"use client";
import { IconSearch } from "@tabler/icons-react";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
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}>
<ComboboxInput
aria-label="Поиск фруктов"
placeholder="Поиск фруктов…"
startAddon={<IconSearch stroke={1.5} />}
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С начальным аддоном — множественный выбор
Используйте свойство startAddon для ComboboxChips, чтобы отобразить иконку в начале при множественном выборе.
"use client";
import { IconSearch } from "@tabler/icons-react";
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxValue,
} from "@/components/ui/combobox";
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 defaultValue={[items[0], items[3]]} items={items} multiple>
<ComboboxChips startAddon={<IconSearch stroke={1.5} />}>
<ComboboxValue>
{(value: { value: string; label: string }[]) => (
<>
{value?.map((item) => (
<ComboboxChip aria-label={item.label} key={item.value}>
{item.label}
</ComboboxChip>
))}
<ComboboxChipsInput
aria-label="Выберите фрукт"
placeholder={value.length > 0 ? undefined : "Выберите фрукт..."}
/>
</>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С полем ввода внутри всплывающего окна
"use client";
import { IconSearch, IconSelector } from "@tabler/icons-react";
import { Button } from "@/components/ui/button";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxTrigger,
ComboboxValue,
} from "@/components/ui/combobox";
interface Country {
code: string;
value: string | null;
continent: string;
label: string;
}
const countries: Country[] = [
{ code: "", continent: "", label: "Выберите страну", value: null },
{ code: "af", continent: "Asia", label: "Афганистан", value: "afghanistan" },
{ code: "al", continent: "Europe", label: "Албания", value: "albania" },
{ code: "dz", continent: "Africa", label: "Алжир", value: "algeria" },
{ code: "ad", continent: "Europe", label: "Андорра", value: "andorra" },
{ code: "ao", continent: "Africa", label: "Ангола", value: "angola" },
{
code: "ar",
continent: "South America",
label: "Аргентина",
value: "argentina",
},
{ code: "am", continent: "Asia", label: "Армения", value: "armenia" },
{ code: "au", continent: "Oceania", label: "Австралия", value: "australia" },
{ code: "at", continent: "Europe", label: "Австрия", value: "austria" },
{ code: "az", continent: "Asia", label: "Азербайджан", value: "azerbaijan" },
{
code: "bs",
continent: "North America",
label: "Багамы",
value: "bahamas",
},
{ code: "bh", continent: "Asia", label: "Бахрейн", value: "bahrain" },
{ code: "bd", continent: "Asia", label: "Бангладеш", value: "bangladesh" },
{
code: "bb",
continent: "North America",
label: "Барбадос",
value: "barbados",
},
{ code: "by", continent: "Europe", label: "Беларусь", value: "belarus" },
{ code: "be", continent: "Europe", label: "Бельгия", value: "belgium" },
{ code: "bz", continent: "North America", label: "Белиз", value: "belize" },
{ code: "bj", continent: "Africa", label: "Бенин", value: "benin" },
{ code: "bt", continent: "Asia", label: "Бутан", value: "bhutan" },
{
code: "bo",
continent: "South America",
label: "Боливия",
value: "bolivia",
},
{
code: "ba",
continent: "Europe",
label: "Босния и Герцеговина",
value: "bosnia-and-herzegovina",
},
{ code: "bw", continent: "Africa", label: "Ботсвана", value: "botswana" },
{
code: "br",
continent: "South America",
label: "Бразилия",
value: "brazil",
},
{ code: "bn", continent: "Asia", label: "Бруней", value: "brunei" },
{ code: "bg", continent: "Europe", label: "Болгария", value: "bulgaria" },
{
code: "bf",
continent: "Africa",
label: "Буркина-Фасо",
value: "burkina-faso",
},
{ code: "bi", continent: "Africa", label: "Бурунди", value: "burundi" },
{ code: "kh", continent: "Asia", label: "Камбоджа", value: "cambodia" },
{ code: "cm", continent: "Africa", label: "Камерун", value: "cameroon" },
{ code: "ca", continent: "North America", label: "Канада", value: "canada" },
{ code: "cv", continent: "Africa", label: "Кабо-Верде", value: "cape-verde" },
{
code: "cf",
continent: "Africa",
label: "Центральноафриканская Республика",
value: "central-african-republic",
},
{ code: "td", continent: "Africa", label: "Чад", value: "chad" },
{ code: "cl", continent: "South America", label: "Чили", value: "chile" },
{ code: "cn", continent: "Asia", label: "Китай", value: "china" },
{
code: "co",
continent: "South America",
label: "Колумбия",
value: "colombia",
},
{ code: "km", continent: "Africa", label: "Коморы", value: "comoros" },
{ code: "cg", continent: "Africa", label: "Конго", value: "congo" },
{
code: "cr",
continent: "North America",
label: "Коста-Рика",
value: "costa-rica",
},
{ code: "hr", continent: "Europe", label: "Хорватия", value: "croatia" },
{ code: "cu", continent: "North America", label: "Куба", value: "cuba" },
{ code: "cy", continent: "Asia", label: "Кипр", value: "cyprus" },
{
code: "cz",
continent: "Europe",
label: "Чехия",
value: "czech-republic",
},
{ code: "dk", continent: "Europe", label: "Дания", value: "denmark" },
{ code: "dj", continent: "Africa", label: "Джибути", value: "djibouti" },
{
code: "dm",
continent: "North America",
label: "Доминика",
value: "dominica",
},
{
code: "do",
continent: "North America",
label: "Доминиканская Республика",
value: "dominican-republic",
},
{
code: "ec",
continent: "South America",
label: "Эквадор",
value: "ecuador",
},
{ code: "eg", continent: "Africa", label: "Египет", value: "egypt" },
{
code: "sv",
continent: "North America",
label: "Сальвадор",
value: "el-salvador",
},
{
code: "gq",
continent: "Africa",
label: "Экваториальная Гвинея",
value: "equatorial-guinea",
},
{ code: "er", continent: "Africa", label: "Эритрея", value: "eritrea" },
{ code: "ee", continent: "Europe", label: "Эстония", value: "estonia" },
{ code: "et", continent: "Africa", label: "Эфиопия", value: "ethiopia" },
{ code: "fj", continent: "Oceania", label: "Фиджи", value: "fiji" },
{ code: "fi", continent: "Europe", label: "Финляндия", value: "finland" },
{ code: "fr", continent: "Europe", label: "Франция", value: "france" },
{ code: "ga", continent: "Africa", label: "Габон", value: "gabon" },
{ code: "gm", continent: "Africa", label: "Гамбия", value: "gambia" },
{ code: "ge", continent: "Asia", label: "Грузия", value: "georgia" },
{ code: "de", continent: "Europe", label: "Германия", value: "germany" },
{ code: "gh", continent: "Africa", label: "Гана", value: "ghana" },
{ code: "gr", continent: "Europe", label: "Греция", value: "greece" },
{
code: "gd",
continent: "North America",
label: "Гренада",
value: "grenada",
},
{
code: "gt",
continent: "North America",
label: "Гватемала",
value: "guatemala",
},
{ code: "gn", continent: "Africa", label: "Гвинея", value: "guinea" },
{
code: "gw",
continent: "Africa",
label: "Гвинея-Бисау",
value: "guinea-bissau",
},
{ code: "gy", continent: "South America", label: "Гайана", value: "guyana" },
{ code: "ht", continent: "North America", label: "Гаити", value: "haiti" },
{
code: "hn",
continent: "North America",
label: "Гондурас",
value: "honduras",
},
{ code: "hu", continent: "Europe", label: "Венгрия", value: "hungary" },
{ code: "is", continent: "Europe", label: "Исландия", value: "iceland" },
{ code: "in", continent: "Asia", label: "Индия", value: "india" },
{ code: "id", continent: "Asia", label: "Индонезия", value: "indonesia" },
{ code: "ir", continent: "Asia", label: "Иран", value: "iran" },
{ code: "iq", continent: "Asia", label: "Ирак", value: "iraq" },
{ code: "ie", continent: "Europe", label: "Ирландия", value: "ireland" },
{ code: "il", continent: "Asia", label: "Израиль", value: "israel" },
{ code: "it", continent: "Europe", label: "Италия", value: "italy" },
{
code: "jm",
continent: "North America",
label: "Ямайка",
value: "jamaica",
},
{ code: "jp", continent: "Asia", label: "Япония", value: "japan" },
{ code: "jo", continent: "Asia", label: "Иордания", value: "jordan" },
{ code: "kz", continent: "Asia", label: "Казахстан", value: "kazakhstan" },
{ code: "ke", continent: "Africa", label: "Кения", value: "kenya" },
{ code: "kw", continent: "Asia", label: "Кувейт", value: "kuwait" },
{ code: "kg", continent: "Asia", label: "Киргизия", value: "kyrgyzstan" },
{ code: "la", continent: "Asia", label: "Лаос", value: "laos" },
{ code: "lv", continent: "Europe", label: "Латвия", value: "latvia" },
{ code: "lb", continent: "Asia", label: "Ливан", value: "lebanon" },
{ code: "ls", continent: "Africa", label: "Лесото", value: "lesotho" },
{ code: "lr", continent: "Africa", label: "Либерия", value: "liberia" },
{ code: "ly", continent: "Africa", label: "Ливия", value: "libya" },
{
code: "li",
continent: "Europe",
label: "Лихтенштейн",
value: "liechtenstein",
},
{ code: "lt", continent: "Europe", label: "Литва", value: "lithuania" },
{ code: "lu", continent: "Europe", label: "Люксембург", value: "luxembourg" },
{ code: "mg", continent: "Africa", label: "Мадагаскар", value: "madagascar" },
{ code: "mw", continent: "Africa", label: "Малави", value: "malawi" },
{ code: "my", continent: "Asia", label: "Малайзия", value: "malaysia" },
{ code: "mv", continent: "Asia", label: "Мальдивы", value: "maldives" },
{ code: "ml", continent: "Africa", label: "Мали", value: "mali" },
{ code: "mt", continent: "Europe", label: "Мальта", value: "malta" },
{
code: "mh",
continent: "Oceania",
label: "Маршалловы Острова",
value: "marshall-islands",
},
{ code: "mr", continent: "Africa", label: "Мавритания", value: "mauritania" },
{ code: "mu", continent: "Africa", label: "Маврикий", value: "mauritius" },
{ code: "mx", continent: "North America", label: "Мексика", value: "mexico" },
{
code: "fm",
continent: "Oceania",
label: "Микронезия",
value: "micronesia",
},
{ code: "md", continent: "Europe", label: "Молдова", value: "moldova" },
{ code: "mc", continent: "Europe", label: "Монако", value: "monaco" },
{ code: "mn", continent: "Asia", label: "Монголия", value: "mongolia" },
{ code: "me", continent: "Europe", label: "Черногория", value: "montenegro" },
{ code: "ma", continent: "Africa", label: "Марокко", value: "morocco" },
{ code: "mz", continent: "Africa", label: "Мозамбик", value: "mozambique" },
{ code: "mm", continent: "Asia", label: "Мьянма", value: "myanmar" },
{ code: "na", continent: "Africa", label: "Намибия", value: "namibia" },
{ code: "nr", continent: "Oceania", label: "Науру", value: "nauru" },
{ code: "np", continent: "Asia", label: "Непал", value: "nepal" },
{
code: "nl",
continent: "Europe",
label: "Нидерланды",
value: "netherlands",
},
{
code: "nz",
continent: "Oceania",
label: "Новая Зеландия",
value: "new-zealand",
},
{
code: "ni",
continent: "North America",
label: "Никарагуа",
value: "nicaragua",
},
{ code: "ne", continent: "Africa", label: "Нигер", value: "niger" },
{ code: "ng", continent: "Africa", label: "Нигерия", value: "nigeria" },
{
code: "kp",
continent: "Asia",
label: "Северная Корея",
value: "north-korea",
},
{
code: "mk",
continent: "Europe",
label: "Северная Македония",
value: "north-macedonia",
},
{ code: "no", continent: "Europe", label: "Норвегия", value: "norway" },
{ code: "om", continent: "Asia", label: "Оман", value: "oman" },
{ code: "pk", continent: "Asia", label: "Пакистан", value: "pakistan" },
{ code: "pw", continent: "Oceania", label: "Палау", value: "palau" },
{ code: "ps", continent: "Asia", label: "Палестина", value: "palestine" },
{ code: "pa", continent: "North America", label: "Панама", value: "panama" },
{
code: "pg",
continent: "Oceania",
label: "Папуа — Новая Гвинея",
value: "papua-new-guinea",
},
{
code: "py",
continent: "South America",
label: "Парагвай",
value: "paraguay",
},
{ code: "pe", continent: "South America", label: "Перу", value: "peru" },
{ code: "ph", continent: "Asia", label: "Филиппины", value: "philippines" },
{ code: "pl", continent: "Europe", label: "Польша", value: "poland" },
{ code: "pt", continent: "Europe", label: "Португалия", value: "portugal" },
{ code: "qa", continent: "Asia", label: "Катар", value: "qatar" },
{ code: "ro", continent: "Europe", label: "Румыния", value: "romania" },
{ code: "ru", continent: "Europe", label: "Россия", value: "russia" },
{ code: "rw", continent: "Africa", label: "Руанда", value: "rwanda" },
{ code: "ws", continent: "Oceania", label: "Самоа", value: "samoa" },
{ code: "sm", continent: "Europe", label: "Сан-Марино", value: "san-marino" },
{
code: "sa",
continent: "Asia",
label: "Саудовская Аравия",
value: "saudi-arabia",
},
{ code: "sn", continent: "Africa", label: "Сенегал", value: "senegal" },
{ code: "rs", continent: "Europe", label: "Сербия", value: "serbia" },
{ code: "sc", continent: "Africa", label: "Сейшелы", value: "seychelles" },
{
code: "sl",
continent: "Africa",
label: "Сьерра-Леоне",
value: "sierra-leone",
},
{ code: "sg", continent: "Asia", label: "Сингапур", value: "singapore" },
{ code: "sk", continent: "Europe", label: "Словакия", value: "slovakia" },
{ code: "si", continent: "Europe", label: "Словения", value: "slovenia" },
{
code: "sb",
continent: "Oceania",
label: "Соломоновы Острова",
value: "solomon-islands",
},
{ code: "so", continent: "Africa", label: "Сомали", value: "somalia" },
{
code: "za",
continent: "Africa",
label: "ЮАР",
value: "south-africa",
},
{ code: "kr", continent: "Asia", label: "Южная Корея", value: "south-korea" },
{
code: "ss",
continent: "Africa",
label: "Южный Судан",
value: "south-sudan",
},
{ code: "es", continent: "Europe", label: "Испания", value: "spain" },
{ code: "lk", continent: "Asia", label: "Шри-Ланка", value: "sri-lanka" },
{ code: "sd", continent: "Africa", label: "Судан", value: "sudan" },
{
code: "sr",
continent: "South America",
label: "Суринам",
value: "suriname",
},
{ code: "se", continent: "Europe", label: "Швеция", value: "sweden" },
{
code: "ch",
continent: "Europe",
label: "Швейцария",
value: "switzerland",
},
{ code: "sy", continent: "Asia", label: "Сирия", value: "syria" },
{ code: "tw", continent: "Asia", label: "Тайвань", value: "taiwan" },
{ code: "tj", continent: "Asia", label: "Таджикистан", value: "tajikistan" },
{ code: "tz", continent: "Africa", label: "Танзания", value: "tanzania" },
{ code: "th", continent: "Asia", label: "Таиланд", value: "thailand" },
{
code: "tl",
continent: "Asia",
label: "Восточный Тимор",
value: "timor-leste",
},
{ code: "tg", continent: "Africa", label: "Того", value: "togo" },
{ code: "to", continent: "Oceania", label: "Тонга", value: "tonga" },
{
code: "tt",
continent: "North America",
label: "Тринидад и Тобаго",
value: "trinidad-and-tobago",
},
{ code: "tn", continent: "Africa", label: "Тунис", value: "tunisia" },
{ code: "tr", continent: "Asia", label: "Турция", value: "turkey" },
{
code: "tm",
continent: "Asia",
label: "Туркменистан",
value: "turkmenistan",
},
{ code: "tv", continent: "Oceania", label: "Тувалу", value: "tuvalu" },
{ code: "ug", continent: "Africa", label: "Уганда", value: "uganda" },
{ code: "ua", continent: "Europe", label: "Украина", value: "ukraine" },
{
code: "ae",
continent: "Asia",
label: "Объединённые Арабские Эмираты",
value: "united-arab-emirates",
},
{
code: "gb",
continent: "Europe",
label: "Великобритания",
value: "united-kingdom",
},
{
code: "us",
continent: "North America",
label: "США",
value: "united-states",
},
{
code: "uy",
continent: "South America",
label: "Уругвай",
value: "uruguay",
},
{ code: "uz", continent: "Asia", label: "Узбекистан", value: "uzbekistan" },
{ code: "vu", continent: "Oceania", label: "Вануату", value: "vanuatu" },
{
code: "va",
continent: "Europe",
label: "Ватикан",
value: "vatican-city",
},
{
code: "ve",
continent: "South America",
label: "Венесуэла",
value: "venezuela",
},
{ code: "vn", continent: "Asia", label: "Вьетнам", value: "vietnam" },
{ code: "ye", continent: "Asia", label: "Йемен", value: "yemen" },
{ code: "zm", continent: "Africa", label: "Замбия", value: "zambia" },
{ code: "zw", continent: "Africa", label: "Зимбабве", value: "zimbabwe" },
];
export default function Particle() {
return (
<Combobox defaultValue={countries[0]} items={countries}>
<ComboboxTrigger
render={
<Button
className="w-full justify-between font-normal"
variant="outline"
/>
}
>
<ComboboxValue />
<IconSelector className="-me-1!" stroke={1.5} />
</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>
{(country: Country) => (
<ComboboxItem key={country.code} value={country}>
{country.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
);
}
С кнопкой в стиле select
Используйте SelectButton как свойство render для ComboboxTrigger, чтобы триггер combobox выглядел как select.
"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 {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
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() {
const [loading, setLoading] = useState(false);
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const selectedItem = formData.get("item");
const itemValue =
items.find((item) => item.label === selectedItem)?.value || selectedItem;
setLoading(true);
await new Promise((r) => setTimeout(r, 800));
setLoading(false);
alert(`Любимый фрукт: ${itemValue || ""}`);
};
return (
<Form className="flex w-full max-w-64 flex-col gap-4" onSubmit={onSubmit}>
<Field name="item">
<FieldLabel>Любимый фрукт</FieldLabel>
<Combobox items={items} required>
<ComboboxInput placeholder="Выберите фрукт..." />
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
<FieldError>Пожалуйста, выберите фрукт.</FieldError>
</Field>
<Button loading={loading} type="submit">
Отправить
</Button>
</Form>
);
}
Интеграция с формой — множественный выбор
"use client";
import type { FormEvent } from "react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxValue,
} from "@/components/ui/combobox";
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
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() {
const [loading, setLoading] = useState(false);
const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const selectedItems = formData.getAll("items");
const itemValues = selectedItems.map(
(selectedItem) =>
items.find((item) => item.label === selectedItem)?.value ||
selectedItem,
);
setLoading(true);
await new Promise((r) => setTimeout(r, 800));
setLoading(false);
alert(`Любимые фрукты: ${itemValues.join(", ") || ""}`);
};
return (
<Form className="flex w-full max-w-64 flex-col gap-4" onSubmit={onSubmit}>
<Field name="items">
<FieldLabel>Любимые фрукты</FieldLabel>
<Combobox items={items} multiple required>
<ComboboxChips>
<ComboboxValue>
{(value: { value: string; label: string }[]) => (
<>
{value?.map((item) => (
<ComboboxChip aria-label={item.label} key={item.value}>
{item.label}
</ComboboxChip>
))}
<ComboboxChipsInput
placeholder={
value.length > 0 ? undefined : "Выберите фрукты…"
}
/>
</>
)}
</ComboboxValue>
</ComboboxChips>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
<FieldError>Пожалуйста, выберите хотя бы один фрукт.</FieldError>
</Field>
<Button loading={loading} type="submit">
Отправить
</Button>
</Form>
);
}
На этой странице