- 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
Field
Компонент, обеспечивающий маркировку и валидацию для элементов управления формы.
Отображается в вашем профиле
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Field>
<FieldLabel>Имя</FieldLabel>
<Input placeholder="Введите ваше имя" type="text" />
<FieldDescription>Отображается в вашем профиле</FieldDescription>
</Field>
);
}
Установка
pnpm dlx shadcn@latest add @oracul/field
Использование
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
FieldValidity,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"<Field>
<FieldLabel>Name</FieldLabel>
<Input type="text" placeholder="Enter your name" />
<FieldDescription>Visible on your profile</FieldDescription>
<FieldError>Please enter a valid name</FieldError>
<FieldValidity>
{(validity) => (
{validity.error && <p>{validity.error}</p>}
)}
</FieldValidity>
</Field>Справочник API
Field
Корневой компонент. Стилизованная обёртка для Field.Root из Base UI с компоновкой flex-колонкой.
FieldLabel
Метка для поля. Стилизованная обёртка для Field.Label из Base UI.
FieldItem
Контейнер для элементов поля. Стилизованная обёртка для Field.Item из Base UI.
FieldDescription
Текст описания для поля. Стилизованная обёртка для Field.Description из Base UI с приглушённым цветом переднего плана.
FieldError
Сообщение об ошибке для поля. Стилизованная обёртка для Field.Error из Base UI с цветом переднего плана для деструктивных действий.
FieldControl
Псевдоним для Field.Control из Base UI. Используйте его, чтобы зарегистрировать собственный или сторонний элемент управления в контексте поля, чтобы он участвовал в маркировке, валидации и обработке состояния ошибки.
Обратите внимание, что Textarea не требует FieldControl — он оборачивает Field.Control внутри себя и интегрируется с Field так же, как Input и другие встроенные элементы управления.
FieldValidity
Псевдоним для Field.Validity из Base UI.
Примеры
Обязательное поле
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Field>
<FieldLabel>
Пароль <span className="text-destructive-foreground">*</span>
</FieldLabel>
<Input placeholder="Введите пароль" required type="password" />
<FieldError>Заполните это поле.</FieldError>
</Field>
);
}
Отключённое поле
Это поле сейчас недоступно.
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function Particle() {
return (
<Field disabled>
<FieldLabel>Эл. почта</FieldLabel>
<Input disabled placeholder="Введите эл. почту" type="email" />
<FieldDescription>Это поле сейчас недоступно.</FieldDescription>
</Field>
);
}
С ошибкой
Введите некорректный адрес электронной почты и нажмите Enter, чтобы увидеть ошибку.
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function FieldWithErrorDemo() {
return (
<Field>
<FieldLabel>Эл. почта</FieldLabel>
<Input placeholder="Введите эл. почту" type="email" />
<FieldError>Введите корректный адрес эл. почты.</FieldError>
</Field>
);
}
С проверкой валидности
{
"state": {
"badInput": false,
"customError": false,
"patternMismatch": false,
"rangeOverflow": false,
"rangeUnderflow": false,
"stepMismatch": false,
"tooLong": false,
"tooShort": false,
"typeMismatch": false,
"valid": null,
"valueMissing": false
},
"error": "",
"errors": [],
"value": null,
"initialValue": null,
"validity": {
"badInput": false,
"customError": false,
"patternMismatch": false,
"rangeOverflow": false,
"rangeUnderflow": false,
"stepMismatch": false,
"tooLong": false,
"tooShort": false,
"typeMismatch": false,
"valid": null,
"valueMissing": false
}
}"use client";
import { Field, FieldLabel, FieldValidity } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export default function FieldWithValidityDemo() {
return (
<Field>
<FieldLabel>Эл. почта</FieldLabel>
<Input placeholder="Введите эл. почту" required type="email" />
<FieldValidity>
{(validity) => (
<div className="flex w-full flex-col gap-2">
{validity.error && (
<p className="text-destructive-foreground text-xs">
{validity.error}
</p>
)}
<div className="w-full rounded-md bg-muted p-2">
<pre className="max-h-60 overflow-y-auto font-mono text-xs [scrollbar-width:none]">
{JSON.stringify(validity, null, 2)}
</pre>
</div>
</div>
)}
</FieldValidity>
</Field>
);
}
Группа полей ввода
import { IconArrowRight } from "@tabler/icons-react";
import { Button } from "@/components/ui/button";
import { Field, FieldError, FieldLabel } from "@/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group";
export default function Particle() {
return (
<Field>
<FieldLabel>Подписка</FieldLabel>
<InputGroup>
<InputGroupInput placeholder="Ваш рабочий адрес" type="email" />
<InputGroupAddon align="inline-end">
<Button aria-label="Подписаться" size="icon-xs" variant="ghost">
<IconArrowRight aria-hidden="true" stroke={1.5} />
</Button>
</InputGroupAddon>
</InputGroup>
<FieldError>Введите корректный адрес эл. почты.</FieldError>
</Field>
);
}
Поле с автодополнением
Выберите вариант.
"use client";
import {
Autocomplete,
AutocompleteEmpty,
AutocompleteInput,
AutocompleteItem,
AutocompleteList,
AutocompletePopup,
} from "@/components/ui/autocomplete";
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
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 (
<Field>
<FieldLabel>Фрукты</FieldLabel>
<Autocomplete items={items}>
<AutocompleteInput
aria-label="Поиск по списку"
placeholder="Поиск по списку…"
/>
<AutocompletePopup>
<AutocompleteEmpty>Ничего не найдено.</AutocompleteEmpty>
<AutocompleteList>
{(item) => (
<AutocompleteItem key={item.value} value={item}>
{item.label}
</AutocompleteItem>
)}
</AutocompleteList>
</AutocompletePopup>
</Autocomplete>
<FieldDescription>Выберите вариант.</FieldDescription>
</Field>
);
}
Поле Combobox
Выберите один вариант.
"use client";
import {
Combobox,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxPopup,
} from "@/components/ui/combobox";
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
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 (
<Field>
<FieldLabel>Фрукты</FieldLabel>
<Combobox items={items}>
<ComboboxInput
aria-label="Выберите вариант"
placeholder="Выберите вариант..."
/>
<ComboboxPopup>
<ComboboxEmpty>Ничего не найдено.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item.value} value={item}>
{item.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxPopup>
</Combobox>
<FieldDescription>Выберите один вариант.</FieldDescription>
</Field>
);
}
Поле Combobox с множественным выбором
Выберите несколько вариантов.
"use client";
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxPopup,
ComboboxValue,
} from "@/components/ui/combobox";
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
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 (
<Field>
<FieldLabel>Фрукты</FieldLabel>
<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>
<FieldDescription>Выберите несколько вариантов.</FieldDescription>
</Field>
);
}
Поле Textarea
Напишите короткую биографию. Не более 500 символов.
"use client";
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
import { Textarea } from "@/components/ui/textarea";
export default function Particle() {
return (
<Field>
<FieldLabel>О себе</FieldLabel>
<Textarea placeholder="Расскажите немного о себе…" />
<FieldDescription>
Напишите короткую биографию. Не более 500 символов.
</FieldDescription>
</Field>
);
}
Поле Select
Необязательное поле
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const items = [
{ label: "Выберите страну", value: null },
{ label: "США", value: "us" },
{ label: "Великобритания", value: "uk" },
{ label: "Канада", value: "ca" },
{ label: "Австралия", value: "au" },
];
export default function Particle() {
return (
<Field>
<FieldLabel>Страна</FieldLabel>
<Select items={items}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
{items.map(({ label, value }) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectPopup>
</Select>
<FieldDescription>Необязательное поле</FieldDescription>
</Field>
);
}
Поле Checkbox
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldLabel } from "@/components/ui/field";
export default function Particle() {
return (
<Field>
<FieldLabel>
<Checkbox />
Принимаю условия использования
</FieldLabel>
</Field>
);
}
Поле группы Checkbox
"use client";
import { Checkbox } from "@/components/ui/checkbox";
import { CheckboxGroup } from "@/components/ui/checkbox-group";
import { Field, FieldItem, FieldLabel } from "@/components/ui/field";
import { Fieldset, FieldsetLegend } from "@/components/ui/fieldset";
export default function Particle() {
return (
<Field
className="gap-2"
name="frameworks"
render={(props) => <Fieldset {...props} />}
>
<FieldsetLegend className="font-medium text-sm">
Фреймворки
</FieldsetLegend>
<CheckboxGroup defaultValue={["react"]}>
<FieldItem>
<FieldLabel>
<Checkbox value="react" /> React
</FieldLabel>
</FieldItem>
<FieldItem>
<FieldLabel>
<Checkbox value="vue" /> Vue
</FieldLabel>
</FieldItem>
<FieldItem>
<FieldLabel>
<Checkbox value="svelte" /> Svelte
</FieldLabel>
</FieldItem>
</CheckboxGroup>
</Field>
);
}
Поле группы Radio
"use client";
import {
Field,
FieldDescription,
FieldItem,
FieldLabel,
} from "@/components/ui/field";
import { Fieldset, FieldsetLegend } from "@/components/ui/fieldset";
import { Radio, RadioGroup } from "@/components/ui/radio-group";
export default function Particle() {
return (
<Field
className="gap-2"
name="plan"
render={(props) => <Fieldset {...props} />}
>
<FieldsetLegend className="font-medium text-sm">
Выберите тариф
</FieldsetLegend>
<RadioGroup defaultValue="free">
<FieldItem>
<FieldLabel>
<Radio value="free" /> Бесплатный
</FieldLabel>
</FieldItem>
<FieldItem>
<FieldLabel>
<Radio value="pro" /> Pro
</FieldLabel>
</FieldItem>
<FieldItem>
<FieldLabel>
<Radio value="enterprise" /> Корпоративный
</FieldLabel>
</FieldItem>
</RadioGroup>
<FieldDescription>Выберите тариф, который вам подходит.</FieldDescription>
</Field>
);
}
Поле Switch
import { Field, FieldLabel } from "@/components/ui/field";
import { Switch } from "@/components/ui/switch";
export default function Particle() {
return (
<Field>
<FieldLabel>
<Switch />
Уведомления по email
</FieldLabel>
</Field>
);
}
Поле Slider
Это необязательное поле
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field";
import { Slider } from "@/components/ui/slider";
export default function Particle() {
return (
<Field className="items-stretch gap-3">
<FieldLabel>Страна</FieldLabel>
<Slider defaultValue={50} />
<FieldDescription>Это необязательное поле</FieldDescription>
</Field>
);
}
Полный пример формы
"use client";
import type { FormEvent } from "react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Field,
FieldDescription,
FieldError,
FieldLabel,
} from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import {
Select,
SelectItem,
SelectPopup,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
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);
const data = {
email: formData.get("email"),
fullName: formData.get("fullName"),
newsletter: formData.get("newsletter"),
role: formData.get("role"),
};
alert(
`Имя и фамилия: ${data.fullName || ""}\nEmail: ${data.email || ""}\nРоль: ${
data.role || ""
}\nРассылка: ${data.newsletter}`,
);
};
return (
<Form className="flex w-full flex-col gap-4" onSubmit={onSubmit}>
<Field name="fullName">
<FieldLabel>
Имя и фамилия <span className="text-destructive">*</span>
</FieldLabel>
<Input placeholder="Иван Иванов" required type="text" />
<FieldError>Введите корректное имя.</FieldError>
</Field>
<Field name="email">
<FieldLabel>
Email <span className="text-destructive">*</span>
</FieldLabel>
<Input placeholder="ivan@example.com" required type="email" />
<FieldError>Введите корректный email.</FieldError>
</Field>
<Field name="role">
<FieldLabel>Роль</FieldLabel>
<Select
items={[
{ label: "Выберите роль", value: null },
{ label: "Разработчик", value: "developer" },
{ label: "Дизайнер", value: "designer" },
{ label: "Продакт-менеджер", value: "manager" },
{ label: "Другое", value: "other" },
]}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectPopup>
<SelectItem value="developer">Разработчик</SelectItem>
<SelectItem value="designer">Дизайнер</SelectItem>
<SelectItem value="manager">Продакт-менеджер</SelectItem>
<SelectItem value="other">Другое</SelectItem>
</SelectPopup>
</Select>
<FieldDescription>Это необязательное поле</FieldDescription>
</Field>
<Field name="newsletter">
<div className="flex items-center gap-2">
<Checkbox />
<FieldLabel className="cursor-pointer">
Подписаться на рассылку
</FieldLabel>
</div>
</Field>
<Button loading={loading} type="submit">
Отправить
</Button>
</Form>
);
}
На этой странице