组件

Form

一个 React 表单,采用 Liquid Glass 布局,提供统一的错误处理与表单级校验。

Form 渲染原生 <form>,并统一协调内部字段的校验与外部错误。它提供表单上下文,让每个 Field 无需单独维护状态就能显示错误。

当多个字段共享同一次提交与错误状态时使用 Form。单个控件请使用 Field;需要把相关字段组织在同一个标题下时,使用 Fieldset。

基础示例

把字段与操作作为 children 传入。Form 使用共享间距提供纵向布局,因此通常只需要通过 className 设置宽度。原生 <form> 元素保留浏览器提交、FormData 与服务端 action 的能力。

We only use this address for account notices.

统一错误

把 errors 设置为以每个 Field 的 name 为 key 的对象。字符串渲染一条信息;数组会渲染其中的每条信息,两条及以上会包裹为列表。Field 会通过 aria-describedby 把信息关联到控件并标记为无效;用户编辑该字段时,Base UI 会清除对应条目。

  • Use a work address.
  • Personal domains are not allowed.
Enter your full name.

As it should appear on the invoice.

Field 自身的 error 属性优先于 Form.errors 中的同名条目。只有通过 Field 渲染的字段会读取错误表;自带标签的控件,例如 Checkbox、Select 与 CheckboxGroup,只有在包裹于具有匹配 name 的 Field 中时才会显示表单错误,否则请对这类控件使用原生约束校验,或在控件旁渲染提示信息。

校验

validationMode 设置表单内所有字段的默认校验时机:

  • onSubmit(默认)在提交时校验,之后每次变更都会重新校验。
  • onBlur 在字段失焦时校验。
  • onChange 在每次变更时校验。

Field 上的 validationMode 属性优先。提交失败后,表单会把焦点移到第一个无效控件,并阻止提交事件。

Use at least four characters.

使用 actionsRef 按需校验。调用 actionsRef.current?.validate() 会校验全部字段;传入名称则只校验一个字段。

const actionsRef = React.useRef<{
  validate: (fieldName?: string) => void;
} | null>(null);

<Form actionsRef={actionsRef}>{/* fields */}</Form>;

actionsRef.current?.validate();
actionsRef.current?.validate("email");

提交值

使用 onFormSubmit 可以直接获得 JavaScript 对象,而不是 FormData 实例。值来自通过 Field 注册的字段,并以它们的 name 为 key。原生提交事件会被自动阻止。

由于对象来自 Field 注册,通过自身 hidden input 提交的控件(例如 Checkbox、Select、Slider、Switch、RadioGroup 与 CheckboxGroup)只有在包裹于 Field 中并以 name 注册时才会包含在内。若它们在 Field 之外使用,且一次提交同时包含这两类控件,请在原生 onSubmit 中从 FormData 读取这些值。

无障碍

Form 渲染原生 <form> 元素,但不会自动添加可访问名称;当页面包含多个表单时,请使用 aria-label 或 aria-labelledby。单个控件的标签来自 Field,提交按钮保留自己的可访问名称。

原生表单行为保持不变:存在提交按钮时,在文本框中按 Enter 会提交,自动填充与 FormData 也能继续使用。Base UI 会关闭浏览器的原生校验气泡,改由 Field 完成校验。提交失败后,焦点会移到第一个无效控件,让键盘与屏幕阅读器用户直接到达问题位置。表单级错误通过控件的 aria-describedby 关系播报。表单模式见可访问性指南。

API 参考

Form

属性类型默认值说明
childrenReactNode—表单内的字段与操作。
errorsRecord<string, string | string[]>—按 Field 的 name 组织的外部错误。字符串渲染一条信息;数组会渲染其中的每条信息,两条及以上会包裹为列表。
onFormSubmit(formValues: Record<string, any>, eventDetails: { reason: "none"; event: Event }) => void—接收通过 Field 注册的控件值,并阻止原生提交事件。
validationMode"onSubmit" | "onBlur" | "onChange""onSubmit"表单内字段的默认校验时机。Field 上的属性优先。
actionsRefRefObject<{ validate: (fieldName?: string) => void } | null>—主动校验全部字段,或按名称校验单个字段。
classNamestring—合并到 form 元素的 Tailwind 类。
styleCSSProperties—内联样式,合并到与 className 相同的元素。
ui{ root?: ClassValue }—按 data-slot 覆盖 root 槽位的 Tailwind 类。
renderReactElement | ((props, state) => ReactElement)—替换表单根元素。

其余 Base UI Form 属性与原生 <form> 属性会透传,包括 action、method、onSubmit、id 与 aria-*。

属性说明
data-slot标记表单根元素(root),用于样式覆盖。

Form 本身不提供额外状态 data-* 属性。

主题

Form 本身没有玻璃表面,会继承页面材质。它的根元素使用纵向堆叠与 gap-4 节奏,并使用共享的 --ui-ink 文字颜色。可以通过 className 覆盖布局,并通过 ui.root 按 data-slot 覆盖表单根元素。Token 分层与预设见主题指南。

相关组件

  • Field — 为单个控件提供标签、说明与统一错误信息。
  • Fieldset — 为一个相关字段组提供共享图例。
  • Button — 使用 type="submit" 提交表单。
  • Input — 放入 Field 的标准文本控件。