Chuyển tới nội dung
Component

Field

One form field: a label, one control, an optional description and an error. Field owns the ids, so the label names the control and the control is described by its description and error, and it passes required, disabled and invalid to both at once.

Xem trước

We send receipts to this address.

Props

  • orientation
  • required
  • disabled
  • invalid
  • label
  • description
  • error
  • optional
  • tooltip
import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm">
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" placeholder="you@example.com" />
  </FieldControl>
  <FieldDescription>We send receipts to this address.</FieldDescription>
</Field>

Cách dùng

Khi nào dùng

  • Any form control with a label, and a description or an error message to go with it.
  • Set required, disabled or invalid once, for the label and the control together.

Khi nào không dùng

  • Two or more controls under one name, such as a date split into day, month and year. Give each its own Field.
  • A control with no visible label, such as a search box in a toolbar. Name it with aria-label instead.

Biến thể

orientation

vertical: the label above the control, for most forms. horizontal: the label beside the control in the first third, for settings pages with short values.

  • We send receipts to this address.

    verticalmặc định

  • We send receipts to this address.

    horizontal

import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm">
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" placeholder="you@example.com" />
  </FieldControl>
  <FieldDescription>We send receipts to this address.</FieldDescription>
</Field>
<Field orientation="horizontal" className="w-full max-w-sm">
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" placeholder="you@example.com" />
  </FieldControl>
  <FieldDescription>We send receipts to this address.</FieldDescription>
</Field>

Ví dụ

Default

We send receipts to this address.

import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm">
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" placeholder="you@example.com" />
  </FieldControl>
  <FieldDescription>We send receipts to this address.</FieldDescription>
</Field>

Required

import { Field, FieldControl, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm" required>
  <FieldLabel>Workspace name</FieldLabel>
  <FieldControl>
    <Input />
  </FieldControl>
</Field>

With an error

The error text marks the input invalid and is read after its name.

Enter an email like you@example.com.

import { Field, FieldControl, FieldError, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm">
  <FieldLabel>Email</FieldLabel>
  <FieldControl>
    <Input type="email" defaultValue="not-an-email" />
  </FieldControl>
  <FieldError>Enter an email like you@example.com.</FieldError>
</Field>

With a select

FieldControl goes around the trigger, so the label opens the list. name and required go on Select.

Admins can invite people and change billing.

import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"

<Field className="w-full max-w-sm">
  <FieldLabel>Role</FieldLabel>
  <Select>
    <FieldControl>
      <SelectTrigger>
        <SelectValue placeholder="Choose a role" />
      </SelectTrigger>
    </FieldControl>
    <SelectContent>
      <SelectItem value="viewer">Viewer</SelectItem>
      <SelectItem value="editor">Editor</SelectItem>
      <SelectItem value="admin">Admin</SelectItem>
    </SelectContent>
  </Select>
  <FieldDescription>Admins can invite people and change billing.</FieldDescription>
</Field>

Disabled

Set when the workspace was created.

import { Field, FieldControl, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

<Field className="w-full max-w-sm" disabled>
  <FieldLabel>Region</FieldLabel>
  <FieldControl>
    <Input defaultValue="Europe" />
  </FieldControl>
  <FieldDescription>Set when the workspace was created.</FieldDescription>
</Field>

Nên và không nên

Nên

  • Use Field for every form control that has a label, so the ids are always linked.
  • Write the error as what to do: Enter an email like you@example.com.
  • Stack fields in a column with gap-lg between them.
  • Set required, disabled and invalid on Field, not on the label and the control one by one.

Không nên

  • Don't put more than one control in a Field; give each its own.
  • Don't set id on the control inside FieldControl; set it on Field, or the label stops pointing at it.
  • Don't show an error before the user has left the field or submitted the form.
  • Don't use the description for an error; use FieldError.

Props

TênKiểuGiá trịMặc địnhMô tả
orientationenumvertical | horizontalverticalvertical: the label above the control, for most forms. horizontal: the label beside the control in the first third, for settings pages with short values.
idstring--Id of the control, for a label or link elsewhere on the page. Generated when left out.
namestring--Form name, passed to the control. For a Select, set name on Select instead.
requiredboolean-falsePuts the asterisk on the label and sets required on the control.
disabledboolean-falseDims the label and disables the control.
invalidboolean-falseSets aria-invalid on the control. A FieldError with text does it on its own; set invalid only when the error shows somewhere else.

Slot

TênBắt buộcMô tả
labelcóFieldLabel with the name of the field.
controlcóFieldControl around one control: Input, or the SelectTrigger of a Select.
descriptionkhôngOptional FieldDescription: what to enter, or why it is needed. One short sentence.
errorkhôngOptional FieldError: what is wrong and how to fix it. Render it only while the value is invalid.

Cấu tạo

PhầnMô tả
rootThe field: a column with the label above the control, or a grid with the label in the first third beside it.
labelFieldLabel: a Label that points at the control and follows the field's required and disabled.
controlFieldControl: wraps the one control (Input, SelectTrigger) and gives it the id, name, state and descriptions. Adds no element.
descriptionFieldDescription: 13px secondary text under the control. Renders only with text.
errorFieldError: 13px danger text under the control. Renders only with text, and then marks the control invalid.

Khả năng truy cập

Role: generic

  • FieldLabel points at the control (htmlFor), so a press on the label focuses it and screen readers read the label as its name.
  • FieldControl gives the control the field's id, and aria-describedby with the description and the error, so screen readers read them after the name.
  • A FieldError with text sets aria-invalid on the control. The error is words, so it never relies on the red edge alone.
  • FieldError is not a live region. After a submit, move focus to the first invalid field; its error is read with it.
  • required puts the asterisk on the label and required on the control, which is what screen readers announce.

Cài đặt

npx shadcn add https://werewolf-ui.vercel.app/r/field.json

Lệnh này thêm luôn styles/werewolf.css, bộ token mà mọi component dùng, và các component khác mà nó cần. Import file đó một lần trong CSS gốc, ngay sau @import "tailwindcss", với đường dẫn tính từ file CSS đó (từ app/globals.css là @import "../styles/werewolf.css").