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.

```tsx demo="forms/input-preview"
```

## Usage

```tsx
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.

```tsx demo="forms/input-adornments"
```

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

```props Input
```

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](/components/system/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.

```tsx demo="forms/password-reveal"
```

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.

```props PasswordInput
```

## 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](/concepts/fields) describes.

## Related

```related textarea, search-input, form
```
