JM Family Design System

Text Input

Text inputs collect short, free-form values. They work best when the user knows the answer and the system gives enough context to enter it correctly.

Guidance for adoption

Start here before choosing examples or props. These notes explain where Text Input helps, where another pattern is better, and what should stay true in product work.

When to use

  • Names and identifiers
  • Short descriptions
  • Search terms
  • Single-line user input

When not to use

  • Long-form writing
  • Known finite options
  • Date, currency, or formatted values without constraints

Accessibility expectations

  • Associate each label with its input.
  • Connect helper and error text with aria-describedby.
  • Use autocomplete where a known browser hint applies.

Content guidance

  • Write labels as short noun phrases that name the value, such as "Vendor email".
  • Use helper text to explain format, constraints, and examples before an error happens.
  • Write error messages that name the problem and the recovery action in plain language.
  • Use placeholder text only for examples; never rely on it as the label or primary instruction.

Implementation notes

  • The label prop is required and wires htmlFor to the generated or provided input id.
  • Helper and error text are connected with aria-describedby; error also sets aria-invalid.
  • Choose the native input type and autocomplete value that match the data being collected.
  • Textarea, leading icons, suffixes, counters, and clear buttons are not part of this API today.

Import

import { TextInput } from '@/components/ui/TextInput';

Label, helper, and error wire to the input via id and aria-describedby automatically.

States

Text inputs need clear state changes without layout shift. Focus should be obvious, conventional, and stable; validation should be direct and recoverable.

Use your legal first and last name.

Default

Ready for user input with a visible label and optional helper text.

Format: name@example.com

Focused

Shows a clear focus ring so the active field is easy to track.

Enter an email address that includes @ and a domain.

Error

Names the problem and tells the user exactly how to fix it.

This value is managed by People Operations.

Disabled

Unavailable because the field is not relevant or cannot be edited in this state.

Anatomy

The visual pieces and the semantic pieces need to stay connected. Helper text and error text should be associated with the field, not simply placed nearby.

Use a short title people can recognize in approvals.

  1. Visible label
  2. Input surface
  3. Typed value
  4. Helper or error text
  5. Programmatic description
  6. Focus and validation state

Props

The component accepts every native HTMLInputElement attribute on top of the design system props below.

PropTypeDefaultDescription
labelReactNodeVisible label rendered above the input. Required for accessibility.
helperReactNodeGuidance text below the input. Auto-wired to aria-describedby.
errorReactNodeError message. Replaces helper text and sets aria-invalid on the input.

Usage rules

Keep labels visible

Labels persist above the field so users always know what the value means, even after typing.

Do not use placeholder text as the label

Placeholder text disappears when users type and creates memory load, especially in longer forms.

Explain format before errors happen

Use helper text for expected formats, constraints, and examples when users need guidance.

Do not validate only at submit

Validate on blur and submit so users can recover close to the field that needs attention.

Known limitations

What Text Input does not do yet, and what consumers need to compose themselves.

  • No leading or trailing slot. Icons, prefixes, suffixes, and clear buttons must be added by wrapping the input or forking the component.
  • No character counter, no required indicator, and no textarea sibling. Multi-line input and length feedback are not part of the API.

Related anti-patterns

Catalog entries to watch for when using Text Input. Read these before shipping; they describe the failure modes the system has already documented.

Agent guidance

Agents should treat labels, helper text, error recovery, and autocomplete as part of the component contract, not optional polish.

Generation rules

  • Every input needs a persistent visible label.
  • Use helper text for format expectations before users make an error.
  • Validate on blur and submit; do not rely on submit-only validation.
  • When marking a field required, render the asterisk in the label text. The component has no required prop, so the visual cue and the aria-required attribute must be wired by the consumer.
  • For leading icons, prefixes, suffixes, or clear buttons, wrap the input in a relatively positioned div and absolutely position the adornment. The component exposes no slot props, so do not fork it for one-off affordances.
  • On submit failure, keep the invalid field enabled and pair the error string with aria-describedby pointing at the helper text id. Disabling the field to prevent further input matches the silently-disabled-buttons anti-pattern.
  • For multi-line input or character counts, do not stretch this component. Use a textarea element directly and apply the same label, helper, and aria-describedby pattern.

Baseline example

import { TextInput } from '@/components/ui/TextInput';

<TextInput
  label="Vendor email"
  name="vendorEmail"
  type="email"
  autoComplete="email"
  helper="Format: name@example.com"
/>
If the value has a strict format such as date, money, phone, or account number, agents should look for a specialized field pattern before using a generic text input.

Focus standard

Inputs should not animate. Use a stable border and focus ring to show the active field without moving the control, shifting text, or introducing unexpected motion into forms.