Form
Form
Form layout wrapper plus FormField, a labelled row that auto-wires id, name, aria-describedby, aria-invalid and aria-required into its child control and renders label, help and error text.
Import
import { Form, FormField, useFormField } from "@zephora/react";Examples
Vertical layout
FormField connects the label and messages to the control automatically.
<Form onSubmit={(e) => e.preventDefault()}>
<FormField name="email" label="Email" help="We never share your email." required>
<Input type="email" placeholder="you@example.com" />
</FormField>
<FormField name="bio" label="Bio">
<Textarea placeholder="Tell us about yourself" />
</FormField>
<Button type="submit">Save</Button>
</Form>Error state
Setting error renders a role="alert" message and marks the control aria-invalid.
<Form>
<FormField
name="username"
label="Username"
error="This username is already taken."
>
<Input defaultValue="admin" />
</FormField>
</Form>Horizontal layout
`layout="horizontal"` puts labels beside their controls.
<Form layout="horizontal" gap={16}>
<FormField name="first" label="First name">
<Input />
</FormField>
<FormField name="last" label="Last name">
<Input />
</FormField>
</Form>API
Form props
| Prop | Type | Default | Description |
|---|---|---|---|
layout | "vertical" | "horizontal" | "vertical" | Field arrangement, inherited by every FormField inside. |
gap | number | string | — | Gap between fields. Numbers are treated as px, strings as CSS lengths. |
unstyled | boolean | false | Headless mode — drops Zephora classes so your own CSS can style it. |
…rest | FormHTMLAttributes<HTMLFormElement> | — | All native form props (onSubmit, action…) are forwarded. |
FormField props
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Name injected into the child control. |
label | ReactNode | — | Label text, wired to the control with htmlFor. |
help | ReactNode | — | Help text announced via aria-describedby. |
error | ReactNode | — | Error message (role="alert"); also sets aria-invalid on the control. |
required | boolean | false | Marks the control as required (aria-required) and shows an asterisk. |
children | ReactNode | — | A single control element; it receives id, name and aria wiring via cloneElement. |
unstyled | boolean | false | Headless mode — drops Zephora classes so your own CSS can style it. |
…rest | HTMLAttributes<HTMLDivElement> | — | Forwarded to the field wrapper element. |
useFormField props
| Prop | Type | Default | Description |
|---|---|---|---|
useFormField() | FormFieldContextValue | null | — | Hook for custom controls: returns the enclosing FormField's { id, helpId, errorId, invalid, required, name } or null outside a FormField. |