BridgeHandbookDraft
For agents
Menu
ExperimentalatomInputs

Input

A one-line text field: names, emails, links.

import { … } from "@brdgapp/ui/components/input"

Usage

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.

When to use

  • Any short typed value in a form: names, emails, links, domains, numbers.

When not to use

  • To search or filter a list. Use SearchInput instead.
  • For a list of short entries, like target roles. Use TagInput instead.
  • For a value that's copied, not typed. Use CopyField instead.

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.

Anatomy

  1. Box. 40px tall (44px on phones), 8px corners, --surface-primary fill, --border-default line, 14px side padding.

  2. Value. 14px --text-primary; 16px on phones, so iPhones don't zoom in when it's tapped.

  3. Placeholder. 14px --text-muted. An example of the format, never the label.

Examples

In a field

With a visible label and help text, tied to it by the Field.

Where intros to you are sent.

The right type

Email, link and name fields get the right phone keyboard and autofill.

States

RestHoverFocusDisabled
Empty
Filled
Invalid
StateWhat happens
RestGrey line.
HoverThe line darkens to --border-hover.
FocusBlue line and a soft blue ring.
InvalidRed line (and a soft red ring on focus). The error text sits under it, in the Field.
Disabled50% opacity; can't be typed in.

Behavior

  • Built on Base UI Input. Inside a Field, its label, help text and error are linked to it automatically.
  • Its look comes from the package. className is for layout only (max-w-sm, flex-1).
  • Same 40px height as SearchInput, so a search box and a field line up in one row.

Do and don't

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 right type (email, url), so phones show the right keyboard.

Don't

Leave every field type="text".

Content

  • Placeholder: an example value, like lanternfield.example. Never the label, never an instruction.

Accessibility

  • Always has a name: a FieldLabel (preferred) or aria-label.
  • Help text and the error are read with it, through the Field.
  • The placeholder uses --text-muted (4.5:1 or more), so it's readable; it still doesn't replace the label.
KeysAction
TabMoves to the next field; in a form, the field you leave is checked.

API reference

Input

The text field, built on Base UI Input. Extends Base UI Input props (value, onChange, onBlur, type, placeholder, disabled, name, autoComplete…).

PropTypeDefaultDescription
typestring"text"email, url, tel, number, password as needed.
aria-invalidboolean—Only outside a Field. Inside one, set invalid on the Field.
classNamestring—Layout only.

Lineage

What it's built from and where it's used, read from the code. When you change it, check these too.

Built from
Nothing else in the package
Used by components
None
Used in patterns
Forms and validation
Used in templates
None

Sources

  • shadcn input (Base UI style), pulled with npm run ui-add, then restyled.
  • Look: Bridge OS src/components/ui/input.tsx and network-entry-modal.tsx (40px, white, 14px), picked by Aman 2026-11-03.