Skip to contentAsheeUIAsheeUI

Input

One line of text, with the label, description and message the field family gives it.

An input collects one line of text: a name, an address, a quantity. It is the plainest member of the field family, so it wears the family's shape rather than its own, a label above the control, a description that says how to fill it in, a message that says what happened, and it resolves density, rounding, treatment and accent through the cascade instead of restating them.

What it adds to the family is two slots at the ends of the control, for a currency symbol, a unit, or a control that acts on the value, and a password form that can reveal what is typed.

Usage

import { Input } from "@asheeui/web";

<Input
  label="Email"
  description="The invoice goes here."
  type="email"
  value={email}
  onChangeText={setEmail}
/>

The change is reported twice, under both names. onChangeText receives the value and onChange receives the event; passing both calls both, so a handler written for the field contract works unchanged on native and a web consumer that needs the event keeps it. Every other input attribute, type, name, placeholder, autoComplete, maxLength, reaches the element.

Adornments

startContent and endContent place a node at either end of the control and shift the text's padding so the value never sits under the adornment. Both accept the framework's own controls as readily as a string.

The two slots differ in one way, and it is the reason the password reveal button works. The start slot is always transparent to the pointer, because a symbol is decoration and a press on it belongs in the field. The end slot is transparent only for a string or a <span>, so a Button placed there keeps its press.

Props

The defaults read as a cascade rather than a list. size, variant and labelAlign are registered by the component as md, bordered and left. radius and color are not registered: they resolve from the application's defaultRadius and defaultColor, so a field rounds and leads with the same accent as the rest of the product. status is never read from configuration, a validation result is a statement about one attempt, not about the design.

size moves height, padding and text together: sm is 2rem high, md 2.5rem, lg 3rem. variant="underlined" resolves the radius to none, since an underlined field with rounded corners is two vocabularies at once.

fullWidth decides whether the field fills its column, the default, and what the control has always done, or shrinks to its content with the label and message alongside, which is what an inline field wants. It resolves through the cascade like every other axis, so components.input.fullWidth retunes every text field at once.

enableVirtualKeyboard defaults to true, but a field opens an on-screen keyboard only when a KeyboardProvider sits above it; without one the prop changes nothing. Passing an object instead of true states the treatment, size, variant, colour and rounding, for that field's keyboard alone, and the layout it opens: enableVirtualKeyboard={{ layout: "numeric" }} gives one field a keypad while the rest of the form keeps the provider's alphabet, and the layout returns to the provider's default when the keyboard closes. See Keyboard.

PasswordInput

PasswordInput is an Input with one addition: a control at the end that reveals what has been typed, and hides it again. The element keeps its password behaviour, it is the toggle that changes type, from password to text and back, so the browser's own manager and its reveal affordance still apply.

The reveal control is a type="button", so it never submits the form it sits in, and it is deliberately outside the tab order: the path from the field to the submit button is the one a keyboard reader takes, and a convenience placed in the middle of it would interrupt. Its name states the state it will move to, Show password, then Hide password, and toggleAriaLabel replaces that wording for a product that names the action differently.

autoComplete defaults to current-password, which is what a sign-in form wants; a sign-up form states new-password instead. type and endContent are not props here: the component owns both, because the reveal control is the end slot.

Accessibility

  • The control is a real <input>. label names it through htmlFor, and the description and message are attached with aria-describedby, so the field is announced with its name and its instructions.
  • status="error" sets aria-invalid, and the message element carries role="alert". A failure is announced when it appears rather than left for a reader who goes looking.
  • isLoading sets aria-busy and adds a spinner beside the label, whose text does not change; disabled uses the element's own attribute, so an unavailable field leaves the tab order while its label and description stay readable.
  • The password toggle is a button whose name states its next state, and it stays out of the tab order so it never stands between the field and the submit button.

The label, description and message behave as the field anatomy describes.