FormField 表单字段

为控件配上标签、说明与错误信息。

公开显示在个人页

import { FormField, Input } from '@hina-ui/react'

export default function Demo() {
  return (
    <FormField label="昵称" description="公开显示在个人页" required className="w-80">
      <Input defaultValue="" placeholder="星见书音" />
    </FormField>
  )
}
tsx

用法

import { FormField } from '@hina-ui/react'
ts

表单字段把一个控件与它的标签、说明和错误信息组成一行。放在 Form 里时,通过 name 取得该字段的错误;单独使用时,通过 error 直接传入错误文字。库里的控件放进字段后会自动关联:标签指向控件,说明与错误信息通过 aria-describedby 关联到控件,出现错误时控件进入无效状态,字段的 disabled 也会传给控件。

import { FormField, Input } from '@hina-ui/react'

export default function Demo() {
  return (
    <FormField label="昵称" className="w-80">
      <Input defaultValue="" />
    </FormField>
  )
}
tsx

示例

横向布局

orientation="horizontal" 将标签放在起始侧,控件放在末端侧。labelWidth 接受 CSS 长度或以像素为单位的数字,默认 10rem。通过 FormLayout 可为多个字段统一标签列宽。横向模式始终保持两列。

显示在你的公开个人资料中。

import { FormField, Input } from '@hina-ui/react'

export default function Demo() {
  return (
    <FormField
      label="显示名称"
      orientation="horizontal"
      labelWidth="8rem"
      description="显示在你的公开个人资料中。"
      className="w-full"
    >
      <Input defaultValue="Hina" />
    </FormField>
  )
}
tsx

说明位置

descriptionPlacement="label" 将说明放在标签下方,阅读顺序也位于控件之前。默认的 control 将说明放在控件下方。错误提示始终留在控件区域。两种位置都支持 description 属性,并保持与控件的无障碍关联。

显示在你的公开个人资料中。

使用可以接收通知的邮箱地址。

请输入邮箱地址。

import { FormField, Input, Stack } from '@hina-ui/react'

export default function Demo() {
  return (
    <Stack className="w-full">
      <FormField
        label="显示名称"
        orientation="responsive"
        descriptionPlacement="label"
        description="显示在你的公开个人资料中。"
      >
        <Input defaultValue="Hina" />
      </FormField>
      <FormField
        label="邮箱地址"
        orientation="responsive"
        descriptionPlacement="control"
        description="使用可以接收通知的邮箱地址。"
        error="请输入邮箱地址。"
      >
        <Input defaultValue="" type="email" />
      </FormField>
    </Stack>
  )
}
tsx

响应式布局

orientation="responsive" 在字段宽度小于 32rem 时纵向排列,达到 32rem 时切为两列。断点依据字段自身的可用宽度,多列表单也按每个字段的列宽判断。拖动示例容器调整宽度即可观察切换。

拖动容器右下角调整宽度;字段宽度小于 32rem 时纵向排列。

import { FormField, Input, Stack } from '@hina-ui/react'

export default function Demo() {
  return (
    <Stack className="w-full max-w-2xl resize-x overflow-auto p-2">
      <FormField
        label="显示名称"
        orientation="responsive"
        description="拖动容器右下角调整宽度;字段宽度小于 32rem 时纵向排列。"
      >
        <Input defaultValue="Hina" />
      </FormField>
    </Stack>
  )
}
tsx

说明文字

description 在控件下方显示一段说明,也可以传入元素放入更丰富的内容。

公开显示在个人页,可以随时修改

不超过 80 个字,支持换行。

import { FormField, Input, Stack, Textarea } from '@hina-ui/react'

export default function Demo() {
  return (
    <Stack gap="md" align="stretch" className="w-80">
      <FormField label="昵称" description="公开显示在个人页,可以随时修改">
        <Input defaultValue="" />
      </FormField>
      <FormField label="简介" description="不超过 80 个字,支持换行。">
        <Textarea defaultValue="" />
      </FormField>
    </Stack>
  )
}
tsx

必填标记

required 在标签后显示必填标记,并给辅助技术提供对应的文字。标记只是提示,是否必填由校验规则决定。

import { FormField, Input } from '@hina-ui/react'

export default function Demo() {
  return (
    <FormField label="邮箱" required className="w-80">
      <Input defaultValue="" type="email" />
    </FormField>
  )
}
tsx

单独使用

不在表单里时,error 直接决定显示的错误文字,适合自行管理校验的场合。

邮箱格式不正确

'use client'

import { useState } from 'react'
import { FormField, Input, Stack, Switch } from '@hina-ui/react'

export default function Demo() {
  const [failed, setFailed] = useState(true)

  return (
    <Stack gap="md" align="stretch" className="w-80">
      <Switch checked={failed} onCheckedChange={setFailed}>
        显示错误
      </Switch>
      <FormField label="邮箱" error={failed ? '邮箱格式不正确' : undefined}>
        <Input defaultValue="shion@example" type="email" />
      </FormField>
    </Stack>
  )
}
tsx

各类控件

单个控件通过标签的 htmlFor 关联;单选组、复选框组、滑块、评分与日期输入这类成组的控件则通过 aria-labelledby 关联到标签。

年
月
日
import {
  CheckboxGroup,
  DateField,
  FormField,
  RadioGroup,
  Rating,
  Slider,
  Stack,
} from '@hina-ui/react'

const kinds = [
  { label: '游戏', value: 'game' },
  { label: '小说', value: 'novel' },
  { label: '漫画', value: 'manga' },
]

export default function Demo() {
  return (
    <Stack gap="md" align="stretch" className="w-80">
      <FormField label="类型">
        <RadioGroup defaultValue="game" options={kinds} orientation="horizontal" />
      </FormField>
      <FormField label="标签">
        <CheckboxGroup defaultValue={[]} options={kinds} orientation="horizontal" />
      </FormField>
      <FormField label="评分">
        <Rating defaultValue={4} />
      </FormField>
      <FormField label="音量">
        <Slider defaultValue={30} />
      </FormField>
      <FormField label="发售日期">
        <DateField defaultValue={null} />
      </FormField>
    </Stack>
  )
}
tsx

行为

  • 一个字段只放一个控件;控件自带的 id 与 aria-describedby 优先于字段生成的值。
  • 错误信息出现时把下方的内容推开,消失时收回,高度与间距连续变化。
  • 字段失去焦点时通知所在的表单,供 blur 校验时机使用。

无障碍

  • 标签通过 htmlFor 指向控件;成组的控件通过 aria-labelledby 关联到标签。
  • 必填标记对辅助技术隐藏,另有隐藏文字说明该字段必填。
  • 错误信息带有 aria-live="polite",出现时会被读出。

API

Props

属性
类型
默认值
说明
name
string
—
字段名,用于从表单取得错误
label
string
—
标签文字
description
string
—
说明文字
error
string
—
直接指定的错误文字
required
boolean
false
是否显示必填标记
orientation
'vertical' | 'horizontal' | 'responsive'
'vertical'
标签与控件的布局,继承 FormLayout 配置
descriptionPlacement
'label' | 'control'
'control'
说明位于标签或控件下方,继承 FormLayout 配置
labelWidth
string | number
'10rem'
标签列宽:CSS 长度或像素数,继承 FormLayout 配置
disabled
boolean
false
是否禁用控件
className
string
—
追加至根元素的类名

内容属性

属性
说明
children
控件
label
标签内容
description
说明内容