Field
StableWraps any form control with a visible label, hint text and an error message, and wires them together.
Also known as form field, form control, form item, label and help text
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
With a hint and an error
Shown in the sidebar.
function Example() {
const [name, setName] = useState("");
const bad = name.length > 0 && name.trim().length < 3;
return (
<div className="w-72">
<Field label="Project name" hint="Shown in the sidebar." error={bad ? "Use at least 3 characters." : undefined} required>
{(a) => <TextField {...a} value={name} onChange={(e) => setName(e.target.value)} placeholder="Q3 planning" />}
</Field>
</div>
);
}Type one or two letters to see the error appear. The message has an icon and words, not only colour.
When to use it
Gives a control a visible name and the help and error text it needs, linked the way assistive technology expects, so each form field is built the same way.
Made of: Label · Required mark or (optional) · Control · Hint · Error with icon
Use it for
- A text, number or select control in a form or settings panel.
- A field that needs help text before the user types.
- A field that shows a message when the value is not accepted.
Not for
- An on-off setting with its label beside it: use Switch.
- A choice between a few options shown side by side: use SegmentedControl.
- The message box in a chat: use Composer.
Do and avoid
We send the invoice here.
Do
- Spread everything the function gives you onto the control.
- Keep the label short and always visible.
- Use hint for rules the user needs before typing, such as a length or format.
- Show the error after the user has left the field or tried to submit.
Avoid
- Do not use a placeholder in place of a label. It disappears when typing starts.
- Do not show an error with colour only. Field always adds an icon and text.
- Do not wrap a Switch in a Field. Put its label beside it.
- Do not write your own id and htmlFor pair. Field makes them for you.
On a phone
- Label, control, hint and error stack in one column at the full width of the container.
- The control inside it follows its own phone rules: 44px tall and 16px text on touch screens.
- The error area is always on the page and is announced without moving focus, so the user is not pulled out of the field.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| labelrequired | string | none | Visible label. It is a real <label> joined to the control with htmlFor. |
| hint | string | none | Help text under the control, linked with aria-describedby. |
| error | string | none | Error message. Shows with a warning icon, sets aria-invalid on the control and is linked with aria-describedby. The message area is always in the page so screen readers announce changes politely. |
| required | boolean | none | Adds an asterisk to the label and passes required to the control. |
| optional | boolean | none | Adds the words (optional) after the label. Ignored when required is set. |
| childrenrequired | (control: { id: string; "aria-describedby"?: string; "aria-invalid"?: boolean; required?: boolean }) => ReactNode | none | Render function. Spread the object it receives onto the control. |
| className | string | none | Classes for the outer stack. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one Field switches all of this from its properties panel, across 8 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Required | required | On or off |
| State | Hover, Pressed and Focus come from the browser. | Default, Hover, Pressed, Focus |
| Label | label | Any text |
| Hint | hint | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- error
- Pass error to show the message with a warning icon under the control, link it with aria-describedby and set aria-invalid on the control.
- hint
- Pass hint to show help text under the control. It is linked with aria-describedby.
- required
- Pass required to add an asterisk to the label and required to the control. optional adds the words (optional) instead.
Tokens
Change one of these and every part that uses it follows.
--fg--fg-muted--danger-fg
Built in
- The label is a real <label> joined to the control, so pressing the label focuses the control.
- The hint and the error are joined to the control with aria-describedby, so they are read when it is focused.
- The error area is always on the page with aria-live set to polite, so a new error is announced without stealing focus.
- The error has a warning icon and words, so colour is not the only clue.
- The asterisk is hidden from screen readers. The control gets the required attribute instead.
What you need to do
- Spread the props the function gives you onto the control. If you skip this, the label is not linked.
- Write error messages that say what is wrong and how to fix it.
- Set error only when the value is wrong, not before the user has had a chance to type.
- For NumberField pass the same text as label, because it needs its own accessible name.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide