Content
- Placeholder: an example value, like
lanternfield.example. Never the label, never an instruction.
A one-line text field: names, emails, links.
import { … } from "@brdgapp/ui/components/input"Input is a one-line text field: a name, an email, a link. Put it inside a Field, which gives it a visible label, help text and an error, all tied to it. The usual mistake is an input with only a placeholder: the hint disappears as soon as someone types, and screen readers lose the name.
The look comes from props
A component's appearance comes only from its own options (variant, size, color). className on a package component is for layout (mt-4, shrink-0, w-full), never for font size, color, padding, radius or hover. If the look needs a className, the component or the chosen option is wrong: fix that instead.
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.
Box. 40px tall (44px on phones), 8px corners, --surface-primary fill, --border-default line, 14px side padding.
Value. 14px --text-primary; 16px on phones, so iPhones don't zoom in when it's tapped.
Placeholder. 14px --text-muted. An example of the format, never the label.
With a visible label and help text, tied to it by the Field.
Where intros to you are sent.
Email, link and name fields get the right phone keyboard and autofill.
| Rest | Hover | Focus | Disabled | |
|---|---|---|---|---|
| Empty | ||||
| Filled | ||||
| Invalid |
| State | What happens |
|---|---|
| Rest | Grey line. |
| Hover | The line darkens to --border-hover. |
| Focus | Blue line and a soft blue ring. |
| Invalid | Red line (and a soft red ring on focus). The error text sits under it, in the Field. |
| Disabled | 50% opacity; can't be typed in. |
className is for layout only (max-w-sm, flex-1).Do
Put it in a Field with a visible label: “Website”.Don't
Use the placeholder as the label: “Enter your website”.Do
Use the righttype (email, url), so phones show the right keyboard.Don't
Leave every fieldtype="text".lanternfield.example. Never the label, never an instruction.aria-label.--text-muted (4.5:1 or more), so it's readable; it still doesn't replace the label.| Keys | Action |
|---|---|
| Tab | Moves to the next field; in a form, the field you leave is checked. |
Input
The text field, built on Base UI Input. Extends Base UI Input props (value, onChange, onBlur, type, placeholder, disabled, name, autoComplete…).
| Prop | Type | Default | Description |
|---|---|---|---|
type | string | "text" | email, url, tel, number, password as needed. |
aria-invalid | boolean | — | Only outside a Field. Inside one, set invalid on the Field. |
className | string | — | Layout only. |
What it's built from and where it's used, read from the code. When you change it, check these too.
input (Base UI style), pulled with npm run ui-add, then restyled.src/components/ui/input.tsx and network-entry-modal.tsx (40px, white, 14px), picked by Aman 2026-11-03.