- 手风琴 Accordion
- 警告 Alert
- 警告对话框 Alert Dialog
- 宽高比 Aspect Ratio
- 头像 Avatar
- 徽章 Badge
- 面包屑 Breadcrumb
- 按钮 Button
- 按钮组 Button Group
- 日历 Calendar
- 卡片 Card
- 轮播图 Carousel
- 图表 Chart
- 复选框 Checkbox
- 折叠面板 Collapsible
- 组合框 Combobox
- 命令菜单 Command
- 上下文菜单 Context Menu
- 数据表格 Data Table
- 日期选择器 Date Picker
- 对话框 Dialog
- 抽屉 Drawer
- 下拉菜单 Dropdown Menu
- 空状态 Empty
- 字段 Field
- 表单 Form
- 悬停卡片 Hover Card
- 输入 Input
- 输入组 Input Group
- 一次性密码 OTP
- 条目 Item
- 快捷键 Kbd
- 标签 Label
- 菜单栏 Menubar
- 导航菜单 Navigation Menu
- 分页 Pagination
- 弹出层 Popover
- 进度 Progress
- 单选框组 Radio Group
- 可调整大小 Resizable
- 滚动区域 Scroll Area
- 选择框 Select
- 分隔符 Separator
- 侧边栏 Sheet
- 侧边栏 Sidebar
- 骨架屏 Skeleton
- 滑块 Slider
- 通知 Sonner
- 加载指示器 Spinner
- 开关 Switch
- 表格 Table
- 标签页 Tabs
- 文本区域 Textarea
- 消息 Toast
- 切换按钮 Toggle
- 切换组 Toggle Group
- 提示 Tooltip
- 排版 Typography
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
export function FieldDemo() {
return (
<div className="w-full max-w-md">
<form>
<FieldGroup>
<FieldSet>
<FieldLegend>Payment Method</FieldLegend>
<FieldDescription>
All transactions are secure and encrypted
</FieldDescription>
<FieldGroup>
<Field>
<FieldLabel htmlFor="checkout-7j9-card-name-43j">
Name on Card
</FieldLabel>
<Input
id="checkout-7j9-card-name-43j"
placeholder="Evil Rabbit"
required
/>
</Field>
<Field>
<FieldLabel htmlFor="checkout-7j9-card-number-uw1">
Card Number
</FieldLabel>
<Input
id="checkout-7j9-card-number-uw1"
placeholder="1234 5678 9012 3456"
required
/>
<FieldDescription>
Enter your 16-digit card number
</FieldDescription>
</Field>
<div className="grid grid-cols-3 gap-4">
<Field>
<FieldLabel htmlFor="checkout-exp-month-ts6">
Month
</FieldLabel>
<Select defaultValue="">
<SelectTrigger id="checkout-exp-month-ts6">
<SelectValue placeholder="MM" />
</SelectTrigger>
<SelectContent>
<SelectItem value="01">01</SelectItem>
<SelectItem value="02">02</SelectItem>
<SelectItem value="03">03</SelectItem>
<SelectItem value="04">04</SelectItem>
<SelectItem value="05">05</SelectItem>
<SelectItem value="06">06</SelectItem>
<SelectItem value="07">07</SelectItem>
<SelectItem value="08">08</SelectItem>
<SelectItem value="09">09</SelectItem>
<SelectItem value="10">10</SelectItem>
<SelectItem value="11">11</SelectItem>
<SelectItem value="12">12</SelectItem>
</SelectContent>
</Select>
</Field>
<Field>
<FieldLabel htmlFor="checkout-7j9-exp-year-f59">
Year
</FieldLabel>
<Select defaultValue="">
<SelectTrigger id="checkout-7j9-exp-year-f59">
<SelectValue placeholder="YYYY" />
</SelectTrigger>
<SelectContent>
<SelectItem value="2024">2024</SelectItem>
<SelectItem value="2025">2025</SelectItem>
<SelectItem value="2026">2026</SelectItem>
<SelectItem value="2027">2027</SelectItem>
<SelectItem value="2028">2028</SelectItem>
<SelectItem value="2029">2029</SelectItem>
</SelectContent>
</Select>
</Field>
<Field>
<FieldLabel htmlFor="checkout-7j9-cvv">CVV</FieldLabel>
<Input id="checkout-7j9-cvv" placeholder="123" required />
</Field>
</div>
</FieldGroup>
</FieldSet>
<FieldSeparator />
<FieldSet>
<FieldLegend>Billing Address</FieldLegend>
<FieldDescription>
The billing address associated with your payment method
</FieldDescription>
<FieldGroup>
<Field orientation="horizontal">
<Checkbox
id="checkout-7j9-same-as-shipping-wgm"
defaultChecked
/>
<FieldLabel
htmlFor="checkout-7j9-same-as-shipping-wgm"
className="font-normal"
>
Same as shipping address
</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
<FieldSet>
<FieldGroup>
<Field>
<FieldLabel htmlFor="checkout-7j9-optional-comments">
Comments
</FieldLabel>
<Textarea
id="checkout-7j9-optional-comments"
placeholder="Add any additional comments"
className="resize-none"
/>
</Field>
</FieldGroup>
</FieldSet>
<Field orientation="horizontal">
<Button type="submit">Submit</Button>
<Button variant="outline" type="button">
Cancel
</Button>
</Field>
</FieldGroup>
</form>
</div>
)
}
安装
pnpm dlx shadcn@latest add field
用法
import {
Field,
FieldContent,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
FieldTitle,
} from "@/components/ui/field"
<FieldSet>
<FieldLegend>个人资料</FieldLegend>
<FieldDescription>此信息将显示在发票和邮件中。</FieldDescription>
<FieldGroup>
<Field>
<FieldLabel htmlFor="name">全名</FieldLabel>
<Input id="name" autoComplete="off" placeholder="邪恶兔子" />
<FieldDescription>此信息将显示在发票和邮件中。</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="username">用户名</FieldLabel>
<Input id="username" autoComplete="off" aria-invalid />
<FieldError>请选择其他用户名。</FieldError>
</Field>
<Field orientation="horizontal">
<Switch id="newsletter" />
<FieldLabel htmlFor="newsletter">订阅新闻通讯</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
结构解析
Field
组件族用于组合无障碍的表单。一个典型的字段结构如下:
<Field>
<FieldLabel htmlFor="input-id">标签</FieldLabel>
{/* 输入框、选择框、开关等控件 */}
<FieldDescription>可选的辅助说明文本。</FieldDescription>
<FieldError>校验信息。</FieldError>
</Field>
Field
是单个字段的核心容器。FieldContent
是一个 flex 列,用于分组标签和描述。如果没有描述,可不使用。- 相关字段可用
FieldGroup
包裹,并用FieldSet
和FieldLegend
做语义分组。
表单集成
查看 表单 文档,了解如何结合 Field
组件与 React Hook Form 或 Tanstack Form 构建表单。
示例
输入框
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function FieldInput() {
return (
<div className="w-full max-w-md">
<FieldSet>
<FieldGroup>
<Field>
<FieldLabel htmlFor="username">Username</FieldLabel>
<Input id="username" type="text" placeholder="Max Leiter" />
<FieldDescription>
Choose a unique username for your account.
</FieldDescription>
</Field>
<Field>
<FieldLabel htmlFor="password">Password</FieldLabel>
<FieldDescription>
Must be at least 8 characters long.
</FieldDescription>
<Input id="password" type="password" placeholder="********" />
</Field>
</FieldGroup>
</FieldSet>
</div>
)
}
多行文本框
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldSet,
} from "@/components/ui/field"
import { Textarea } from "@/components/ui/textarea"
export function FieldTextarea() {
return (
<div className="w-full max-w-md">
<FieldSet>
<FieldGroup>
<Field>
<FieldLabel htmlFor="feedback">Feedback</FieldLabel>
<Textarea
id="feedback"
placeholder="Your feedback helps us improve..."
rows={4}
/>
<FieldDescription>
Share your thoughts about our service.
</FieldDescription>
</Field>
</FieldGroup>
</FieldSet>
</div>
)
}
选择框
Select your department or area of work.
import {
Field,
FieldDescription,
FieldLabel,
} from "@/components/ui/field"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export function FieldSelect() {
return (
<div className="w-full max-w-md">
<Field>
<FieldLabel>Department</FieldLabel>
<Select>
<SelectTrigger>
<SelectValue placeholder="Choose department" />
</SelectTrigger>
<SelectContent>
<SelectItem value="engineering">Engineering</SelectItem>
<SelectItem value="design">Design</SelectItem>
<SelectItem value="marketing">Marketing</SelectItem>
<SelectItem value="sales">Sales</SelectItem>
<SelectItem value="support">Customer Support</SelectItem>
<SelectItem value="hr">Human Resources</SelectItem>
<SelectItem value="finance">Finance</SelectItem>
<SelectItem value="operations">Operations</SelectItem>
</SelectContent>
</Select>
<FieldDescription>
Select your department or area of work.
</FieldDescription>
</Field>
</div>
)
}
滑块
Set your budget range ($200 - 800).
"use client"
import { useState } from "react"
import {
Field,
FieldDescription,
FieldTitle,
} from "@/components/ui/field"
import { Slider } from "@/components/ui/slider"
export function FieldSlider() {
const [value, setValue] = useState([200, 800])
return (
<div className="w-full max-w-md">
<Field>
<FieldTitle>Price Range</FieldTitle>
<FieldDescription>
Set your budget range ($
<span className="font-medium tabular-nums">{value[0]}</span> -{" "}
<span className="font-medium tabular-nums">{value[1]}</span>).
</FieldDescription>
<Slider
value={value}
onValueChange={setValue}
max={1000}
min={0}
step={10}
className="mt-2 w-full"
aria-label="Price Range"
/>
</Field>
</div>
)
}
字段集
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
export function FieldFieldset() {
return (
<div className="w-full max-w-md space-y-6">
<FieldSet>
<FieldLegend>Address Information</FieldLegend>
<FieldDescription>
We need your address to deliver your order.
</FieldDescription>
<FieldGroup>
<Field>
<FieldLabel htmlFor="street">Street Address</FieldLabel>
<Input id="street" type="text" placeholder="123 Main St" />
</Field>
<div className="grid grid-cols-2 gap-4">
<Field>
<FieldLabel htmlFor="city">City</FieldLabel>
<Input id="city" type="text" placeholder="New York" />
</Field>
<Field>
<FieldLabel htmlFor="zip">Postal Code</FieldLabel>
<Input id="zip" type="text" placeholder="90502" />
</Field>
</div>
</FieldGroup>
</FieldSet>
</div>
)
}
复选框
Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,
FieldContent,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from "@/components/ui/field"
export function FieldCheckbox() {
return (
<div className="w-full max-w-md">
<FieldGroup>
<FieldSet>
<FieldLegend variant="label">
Show these items on the desktop
</FieldLegend>
<FieldDescription>
Select the items you want to show on the desktop.
</FieldDescription>
<FieldGroup className="gap-3">
<Field orientation="horizontal">
<Checkbox id="finder-pref-9k2-hard-disks-ljj" />
<FieldLabel
htmlFor="finder-pref-9k2-hard-disks-ljj"
className="font-normal"
defaultChecked
>
Hard disks
</FieldLabel>
</Field>
<Field orientation="horizontal">
<Checkbox id="finder-pref-9k2-external-disks-1yg" />
<FieldLabel
htmlFor="finder-pref-9k2-external-disks-1yg"
className="font-normal"
>
External disks
</FieldLabel>
</Field>
<Field orientation="horizontal">
<Checkbox id="finder-pref-9k2-cds-dvds-fzt" />
<FieldLabel
htmlFor="finder-pref-9k2-cds-dvds-fzt"
className="font-normal"
>
CDs, DVDs, and iPods
</FieldLabel>
</Field>
<Field orientation="horizontal">
<Checkbox id="finder-pref-9k2-connected-servers-6l2" />
<FieldLabel
htmlFor="finder-pref-9k2-connected-servers-6l2"
className="font-normal"
>
Connected servers
</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
<FieldSeparator />
<Field orientation="horizontal">
<Checkbox id="finder-pref-9k2-sync-folders-nep" defaultChecked />
<FieldContent>
<FieldLabel htmlFor="finder-pref-9k2-sync-folders-nep">
Sync Desktop & Documents folders
</FieldLabel>
<FieldDescription>
Your Desktop & Documents folders are being synced with iCloud
Drive. You can access them from other devices.
</FieldDescription>
</FieldContent>
</Field>
</FieldGroup>
</div>
)
}
单选框
import {
Field,
FieldDescription,
FieldLabel,
FieldSet,
} from "@/components/ui/field"
import {
RadioGroup,
RadioGroupItem,
} from "@/components/ui/radio-group"
export function FieldRadio() {
return (
<div className="w-full max-w-md">
<FieldSet>
<FieldLabel>Subscription Plan</FieldLabel>
<FieldDescription>
Yearly and lifetime plans offer significant savings.
</FieldDescription>
<RadioGroup defaultValue="monthly">
<Field orientation="horizontal">
<RadioGroupItem value="monthly" id="plan-monthly" />
<FieldLabel htmlFor="plan-monthly" className="font-normal">
Monthly ($9.99/month)
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="yearly" id="plan-yearly" />
<FieldLabel htmlFor="plan-yearly" className="font-normal">
Yearly ($99.99/year)
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="lifetime" id="plan-lifetime" />
<FieldLabel htmlFor="plan-lifetime" className="font-normal">
Lifetime ($299.99)
</FieldLabel>
</Field>
</RadioGroup>
</FieldSet>
</div>
)
}
开关
Enable multi-factor authentication. If you do not have a two-factor device, you can use a one-time code sent to your email.
import {
Field,
FieldContent,
FieldDescription,
FieldLabel,
} from "@/components/ui/field"
import { Switch } from "@/components/ui/switch"
export function FieldSwitch() {
return (
<div className="w-full max-w-md">
<Field orientation="horizontal">
<FieldContent>
<FieldLabel htmlFor="2fa">Multi-factor authentication</FieldLabel>
<FieldDescription>
Enable multi-factor authentication. If you do not have a two-factor
device, you can use a one-time code sent to your email.
</FieldDescription>
</FieldContent>
<Switch id="2fa" />
</Field>
</div>
)
}
选择卡片
将多个 Field
组件包裹于 FieldLabel
中,创建可选择的字段组。支持与 RadioItem
、Checkbox
和 Switch
组件搭配使用。
import {
Field,
FieldContent,
FieldDescription,
FieldGroup,
FieldLabel,
FieldSet,
FieldTitle,
} from "@/components/ui/field"
import {
RadioGroup,
RadioGroupItem,
} from "@/components/ui/radio-group"
export function FieldChoiceCard() {
return (
<div className="w-full max-w-md">
<FieldGroup>
<FieldSet>
<FieldLabel htmlFor="compute-environment-p8w">
Compute Environment
</FieldLabel>
<FieldDescription>
Select the compute environment for your cluster.
</FieldDescription>
<RadioGroup defaultValue="kubernetes">
<FieldLabel htmlFor="kubernetes-r2h">
<Field orientation="horizontal">
<FieldContent>
<FieldTitle>Kubernetes</FieldTitle>
<FieldDescription>
Run GPU workloads on a K8s configured cluster.
</FieldDescription>
</FieldContent>
<RadioGroupItem value="kubernetes" id="kubernetes-r2h" />
</Field>
</FieldLabel>
<FieldLabel htmlFor="vm-z4k">
<Field orientation="horizontal">
<FieldContent>
<FieldTitle>Virtual Machine</FieldTitle>
<FieldDescription>
Access a VM configured cluster to run GPU workloads.
</FieldDescription>
</FieldContent>
<RadioGroupItem value="vm" id="vm-z4k" />
</Field>
</FieldLabel>
</RadioGroup>
</FieldSet>
</FieldGroup>
</div>
)
}
字段组
使用 FieldGroup
堆叠多个 Field
组件。添加 FieldSeparator
用以分隔。
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldSeparator,
FieldSet,
} from "@/components/ui/field"
export function FieldGroupExample() {
return (
<div className="w-full max-w-md">
<FieldGroup>
<FieldSet>
<FieldLabel>Responses</FieldLabel>
<FieldDescription>
Get notified when ChatGPT responds to requests that take time, like
research or image generation.
</FieldDescription>
<FieldGroup data-slot="checkbox-group">
<Field orientation="horizontal">
<Checkbox id="push" defaultChecked disabled />
<FieldLabel htmlFor="push" className="font-normal">
Push notifications
</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
<FieldSeparator />
<FieldSet>
<FieldLabel>Tasks</FieldLabel>
<FieldDescription>
Get notified when tasks you've created have updates.{" "}
<a href="#">Manage tasks</a>
</FieldDescription>
<FieldGroup data-slot="checkbox-group">
<Field orientation="horizontal">
<Checkbox id="push-tasks" />
<FieldLabel htmlFor="push-tasks" className="font-normal">
Push notifications
</FieldLabel>
</Field>
<Field orientation="horizontal">
<Checkbox id="email-tasks" />
<FieldLabel htmlFor="email-tasks" className="font-normal">
Email notifications
</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
</FieldGroup>
</div>
)
}
响应式布局
- 垂直字段: 默认方向是标签、控件和辅助文本垂直堆叠,适合移动优先布局。
- 水平字段: 在
Field
上设置orientation="horizontal"
,使标签和控件并排。配合FieldContent
保持描述对齐。 - 响应式字段: 设为
orientation="responsive"
,在容器感知的父元素内自动切换列布局。在FieldGroup
上添加@container/field-group
类,可在特定断点切换方向。
import { Button } from "@/components/ui/button"
import {
Field,
FieldContent,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
export function FieldResponsive() {
return (
<div className="w-full max-w-4xl">
<form>
<FieldSet>
<FieldLegend>Profile</FieldLegend>
<FieldDescription>Fill in your profile information.</FieldDescription>
<FieldSeparator />
<FieldGroup>
<Field orientation="responsive">
<FieldContent>
<FieldLabel htmlFor="name">Name</FieldLabel>
<FieldDescription>
Provide your full name for identification
</FieldDescription>
</FieldContent>
<Input id="name" placeholder="Evil Rabbit" required />
</Field>
<FieldSeparator />
<Field orientation="responsive">
<FieldContent>
<FieldLabel htmlFor="lastName">Message</FieldLabel>
<FieldDescription>
You can write your message here. Keep it short, preferably
under 100 characters.
</FieldDescription>
</FieldContent>
<Textarea
id="message"
placeholder="Hello, world!"
required
className="min-h-[100px] resize-none sm:min-w-[300px]"
/>
</Field>
<FieldSeparator />
<Field orientation="responsive">
<Button type="submit">Submit</Button>
<Button type="button" variant="outline">
Cancel
</Button>
</Field>
</FieldGroup>
</FieldSet>
</form>
</div>
)
}
验证与错误提示
- 在
Field
上添加data-invalid
,将整个块切换为错误状态。 - 在输入控件本身添加
aria-invalid
,增强辅助技术支持。 - 将
FieldError
渲染在控件后面或放入FieldContent
,保持错误信息与字段对齐。
<Field data-invalid>
<FieldLabel htmlFor="email">电子邮箱</FieldLabel>
<Input id="email" type="email" aria-invalid />
<FieldError>请输入有效的电子邮箱地址。</FieldError>
</Field>
无障碍支持
FieldSet
和FieldLegend
用于将相关控件分组,便于键盘和辅助技术用户操作。Field
输出role="group"
,嵌套控件可继承来自FieldLabel
和FieldLegend
的标签。- 谨慎使用
FieldSeparator
,保证屏幕阅读器识别清晰的区域边界。
API 参考
FieldSet
语义容器,渲染 fieldset
,带有预设间距。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<FieldSet>
<FieldLegend>递送信息</FieldLegend>
<FieldGroup>{/* 字段们 */}</FieldGroup>
</FieldSet>
FieldLegend
FieldSet
的标题元素。切换到 label
变体可以配合标签大小对齐。
属性 | 类型 | 默认值 |
---|---|---|
variant | "legend" | "label" | "legend" |
className | string |
<FieldLegend variant="label">通知偏好</FieldLegend>
FieldLegend
有两个变体:legend
和 label
。label
变体应用标签大小和对齐,适用于嵌套的 FieldSet
。
FieldGroup
布局容器,堆叠 Field
组件并支持响应式容器查询。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<FieldGroup className="@container/field-group flex flex-col gap-6">
<Field>{/* ... */}</Field>
<Field>{/* ... */}</Field>
</FieldGroup>
Field
单个字段的核心外壳。提供方向控制、无效态样式和间距。
属性 | 类型 | 默认值 |
---|---|---|
orientation | "vertical" | "horizontal" | "responsive" | "vertical" |
className | string | |
data-invalid | boolean |
<Field orientation="horizontal">
<FieldLabel htmlFor="remember">记住我</FieldLabel>
<Switch id="remember" />
</Field>
FieldContent
flex 列,用于标签旁边含描述时分组控件和说明。无说明时可不使用。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<Field>
<Checkbox id="notifications" />
<FieldContent>
<FieldLabel htmlFor="notifications">通知</FieldLabel>
<FieldDescription>邮箱、短信及推送选项。</FieldDescription>
</FieldContent>
</Field>
FieldLabel
标签,适用于直接输入控件或嵌套 Field
的子元素。
属性 | 类型 | 默认值 |
---|---|---|
className | string | |
asChild | boolean | false |
<FieldLabel htmlFor="email">电子邮箱</FieldLabel>
FieldTitle
在 FieldContent
内渲染带标签样式的标题。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<FieldContent>
<FieldTitle>启用 Touch ID</FieldTitle>
<FieldDescription>更快解锁设备。</FieldDescription>
</FieldContent>
FieldDescription
辅助文本槽,在水平布局中自动平衡长行。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<FieldDescription>我们绝不向他人泄露您的邮箱。</FieldDescription>
FieldSeparator
视视觉分隔线,用于 FieldGroup
内部分割区块。可接受内联内容。
属性 | 类型 | 默认值 |
---|---|---|
className | string |
<FieldSeparator>或继续使用</FieldSeparator>
FieldError
无障碍错误容器,支持子节点或 errors
数组(例如来自 react-hook-form
)。
属性 | 类型 | 默认值 |
---|---|---|
errors | Array<{ message?: string } | undefined> | |
className | string |
<FieldError errors={errors.username} />
当 errors
数组包含多条消息时,组件会自动渲染列表。
FieldError
也支持任何实现了 标准 Schema 的验证器生成的问题数组,如 Zod、Valibot 和 ArkType。直接传入 Schema 结果中的 issues
数组即可跨库统一渲染错误列表。