Skip to content
View as Markdown

Inputs

Input

The single-line text box. Compose it inside a Field for its label, description and error.

Import

import { Field, Input } from "@loamui/core";

Usage

Every example has a CSStab. That’s the real, complete stylesheet for the component: plain, static CSS, with nothing running in the browser.

Basic usage

Wrap the control in Field.Root and add a Field.Label: the input reads its id from the field, so the label is wired without any props.

Size from context

There is no size prop. Padding and font are fluid container-relative tokens: the control adapts to the space it lives in, and always height-aligns with Button, which shares the same derived anatomy. See the Contextualism guide.

Description & required

This will be your public handle.

Error state

A Field.Error before the control marks the field invalid and is announced: no error prop, the message's presence is the state.

Native validation

Native constraints such as required and type="email" are announced and styled after a submit attempt, not on blur. Existing errors clear as soon as the value becomes valid.

With sections

Sections sit inside the field but outside the accessible name, so the Field.Label still does the naming. A placeholder alone never can.

@
.dev

Guidance

When to use it

  • For short, free-form single-line text: names, emails, search terms, URLs.
  • Inside a Field.Root, which ties the label, helper description and inline error together: the control self-wires from the surrounding field, so the accessibility is correct by construction. See the Field page.

When not to

  • For multi-line text: use Textarea.
  • For choosing from a fixed set of options: use Select, Radio or Checkbox.

Accessibility

  • Inside a Field.Root the input reads its id from the field, so Field.Label is a real <label> tied to it: clicking the label focuses the field and screen readers announce it.
  • Field.Description and Field.Error are linked via aria-describedby, and a rendered error also sets aria-invalid, announced together when the field gains focus.
  • Field.Error uses role="alert" so the message is announced as it appears.
  • leftSection / rightSection render your content beside the input but outside its accessible name. Mark visual content like currency symbols or icons aria-hidden, and carry the unit in the label or description so non-visual users get it too.
  • Mark optional fields in words (Field.Label's optional prop) rather than asterisking required ones: required lives on the control as the native required attribute, which drives validation after submission.

How it works

Asking for numbers

Never use type="number": scroll wheels and arrow keys silently change the value, and browsers give poor feedback when the input is invalid. Pass inputMode="numeric" for whole numbers or inputMode="decimal" for amounts (both forward straight to the native input) so touch devices raise a number pad while the field keeps normal text behaviour.

Codes and references

Values users copy rather than compose (booking references, invoice numbers, licence keys) are not words, so set spellCheck={false} to stop browsers underlining a correct value as a mistake. A digits-only reference also takes inputMode="numeric".

Autofill and input purpose

Any field asking for something about the user gets the matching autoComplete value: "name", "email", "postal-code", "bday-day" and the rest of the HTML autofill set, forwarded straight through. This is WCAG 1.3.5 (Identify Input Purpose): it lets browsers fill the answer correctly and lets assistive tech present the field in the user’s own terms.

Placeholders are not labels

A placeholder vanishes the moment the user types, is skipped by some assistive technology, and its dimmed colour fails contrast as instruction text. Field.Label is for what the field is; format hints go in Field.Description, which stays visible and is announced. These docs use none at all: the example lives in Field.Description, where it survives typing.

Width belongs to the container

The field fills whatever it is placed in; there is no size or width prop. Width is information: a four-character reference in a page-wide box reads as a harder question than it is, so put the field in a container sized to the expected answer.

Error messages

Say what happened and how to fix it, in the words of the question itself. See the writing guidance on the Field page.

SituationMessage
The field is emptyEnter [whatever the label asks for]
The value is the wrong formatEnter [a/an] [thing] in the correct format, like [example]
The value is too long / too short[Label] must be [N] characters or fewer / or more
The value contains a disallowed character[Label] must only include [allowed characters]
A number is out of range[Label] must be between [min] and [max]

Props

PropTypeDefaultDescription
leftSectionReactNodeContent inside the field, before the input.
rightSectionReactNodeContent inside the field, after the input.
wrapperClassNamestringClass for the bordered field wrapper; className goes to the control itself.
...othersInputHTMLAttributesAll native <input> props are forwarded, except size (sizing is contextual).