Content
- Label: a short noun, sentence case, no colon. “Network name”.
- Help text: what it's for, before the mistake. “Adds the logo and links to the network page.”
- Error: the fix, with an example that works.
A label, a control, help text and an error, tied together.
import { … } from "@brdgapp/ui/components/field"Field holds one form question: its label, the control (an Input, a TagInput), help text and the error, tied together so they're read as one. FieldGroup stacks fields 16px apart. The usual mistake is wiring labels and errors by hand and missing one, so a screen reader hears a box with no name or an error with no field.
Every control has a name
Every control says what it does to a screen reader. An icon-only button carries an aria-label naming the action ("Close", not "X"); a group of filters or a table has a name; a tooltip is never the only name.
Adds the logo and links to the network page.
Label. 14px medium --text-primary, above the control. Sentence case, no colon.
Optional mark. “(optional)” in muted text after the label, on fields people can skip. Required fields get no mark.
Control. The Input, TagInput or other control, 6px under the label.
Help text. 12px --text-muted under the control: what the value is for.
Error. 12px --danger-text with a small alert icon, under the control. Says how to fix it.
Press Add network with the name empty, or type “lanternfield” as the website and press Tab. Errors appear when you leave a field or save, and go as soon as the value works.
Under the field, with an icon, saying how to fix it.
| State | What happens |
|---|---|
| Default | Label, control, help text. |
| Invalid | invalid on the Field: the control turns red and FieldError shows its message. |
| Disabled | disabled on the Field disables the control and dims the label. |
aria-describedby. No ids to write.Do
Mark the fields people can skip withoptional.Don't
Put a red asterisk on the required ones.Do
Say how to fix it: “Enter a domain, like lanternfield.example”.Don't
Say “Invalid” or “This field is required”.| Keys | Action |
|---|---|
| Tab | Moves to the next field, and checks the one you left. |
Field
One question. Built on Base UI Field.
| Prop | Type | Default | Description |
|---|---|---|---|
invalid | boolean | — | The value has a problem: the control turns red and FieldError shows. |
disabled | boolean | — | Disables the control and dims the label. |
name | string | — | The form name of the control. |
className | string | — | Layout only. |
FieldLabel
The visible label, tied to the control.
| Prop | Type | Default | Description |
|---|---|---|---|
optional | boolean | false | Adds “(optional)” after the label. |
FieldDescription
Help text under the control, read with it.
| Prop | Type | Default | Description |
|---|
FieldError
The error under the control. Renders only when it has text.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The message: how to fix it. |
FieldGroup
Stacks fields 16px apart.
| Prop | Type | Default | Description |
|---|
What it's built from and where it's used, read from the code. When you change it, check these too.
field (Base UI style), pulled with npm run ui-add, cut down to Field, FieldLabel, FieldDescription, FieldError and FieldGroup, and built on Base UI Field.network-entry-modal.tsx → FieldError (icon + 12px text).