# Input

A single-line text field for typing a value, such as a name, a domain, an IP range or a search query.

```tsx
import { Input } from "@zenoxai/ui/components/input"

function InputDemo() {
  return (
    <Input
      type="search"
      placeholder="Search alerts"
      aria-label="Search alerts"
      className="max-w-xs"
    />
  )
}
```

## Usage

```tsx
import { Input } from "@zenoxai/ui/components/input"

<Input type="email" placeholder="soc@acme.com" />
```

`Input` renders a native `<input>` and accepts all of its attributes: `type`, `value`,
`defaultValue`, `onChange`, `name`, `required`, `pattern`, `autoComplete`. It is 32px tall
(`size="default"`) and fills the width of its container; constrain it with a width class or
the layout around it. The `size` prop sets the height, so the native `size` attribute (a width
in characters) is not available.

Pick a more specific control when the value has a shape:

| Value                                   | Use                                      |
| --------------------------------------- | ---------------------------------------- |
| A number with a range or a step         | [Number Input](/components/number-input) |
| One option from a fixed list            | [Select](/components/select)             |
| One option from a long, searchable list | [Combobox](/components/combobox)         |
| A one-time code                         | [Input OTP](/components/input-otp)       |
| Several lines of text                   | [Textarea](/components/textarea)         |
| An icon, a prefix or a button inside    | [Input Group](/components/input-group)   |

A `type="search"` field shows no browser clear button: each browser draws its own, and they do
not match the rest of the interface. When a search field needs a clear action, build it with
an [Input Group](/components/input-group) and a clear button, as in its first example.

## Examples

### With a label

Wrap the input in a [Field](/components/field) with a `FieldLabel` and, when the value needs
explaining, a `FieldDescription`. A placeholder is an example value, never the label: it
disappears as soon as the user types.

```tsx
import { Field, FieldDescription, FieldLabel } from "@zenoxai/ui/components/field"
import { Input } from "@zenoxai/ui/components/input"

function InputWithLabel() {
  return (
    <Field className="max-w-sm">
      <FieldLabel htmlFor="report-recipient">Report recipient</FieldLabel>
      <Input
        id="report-recipient"
        type="email"
        placeholder="soc@acme.com"
        aria-describedby="report-recipient-description"
      />
      <FieldDescription id="report-recipient-description">
        Receives the weekly vulnerability report.
      </FieldDescription>
    </Field>
  )
}
```

### Sizes

`size="sm"` (28px) fits toolbars and filter bars, `default` (32px) is the form size and `lg`
(36px) suits a search field on an empty state. The sizes match the heights of
[Button](/components/button), Select, Number Input and Input Group, so a field and the button
next to it line up.

```tsx
import { Input } from "@zenoxai/ui/components/input"

function InputSizes() {
  return (
    <div className="flex w-full max-w-xs flex-col gap-3">
      <Input size="sm" placeholder="Filter assets" aria-label="Filter assets" />
      <Input placeholder="Search alerts" aria-label="Search alerts" />
      <Input
        size="lg"
        placeholder="Search domains"
        aria-label="Search domains"
      />
    </div>
  )
}
```

### Invalid

Set `aria-invalid` on the input and `data-invalid` on the `Field`, and put the message in a
`FieldError` linked through `aria-describedby`.

```tsx
import { Field, FieldError, FieldLabel } from "@zenoxai/ui/components/field"
import { Input } from "@zenoxai/ui/components/input"

function InputInvalid() {
  return (
    <Field data-invalid className="max-w-sm">
      <FieldLabel htmlFor="allowed-ip">Allowed IP range</FieldLabel>
      <Input
        id="allowed-ip"
        defaultValue="10.0.0.0/33"
        aria-invalid
        aria-describedby="allowed-ip-error"
      />
      <FieldError id="allowed-ip-error">
        Enter a CIDR range with a prefix from 0 to 32.
      </FieldError>
    </Field>
  )
}
```

### Read-only and disabled

Use `readOnly` for a value the user can see, select and copy but not change, such as an ID.
Use `disabled` for a value that does not apply right now; it is skipped by keyboard focus and
not submitted with the form. A disabled field is dimmed to 50%, like every disabled control.
Set `data-disabled` on the `Field` to dim the label too.

```tsx
import { Field, FieldLabel } from "@zenoxai/ui/components/field"
import { Input } from "@zenoxai/ui/components/input"

function InputDisabled() {
  return (
    <div className="grid w-full max-w-sm gap-4">
      <Field>
        <FieldLabel htmlFor="tenant-id">Tenant ID</FieldLabel>
        <Input id="tenant-id" defaultValue="tnt_8f3k2m9q" readOnly />
      </Field>
      <Field data-disabled>
        <FieldLabel htmlFor="sso-domain">SSO domain</FieldLabel>
        <Input id="sso-domain" defaultValue="acme.okta.com" disabled />
      </Field>
    </div>
  )
}
```

### File

`type="file"` styles the native file button to match the input. Restrict the file types with
`accept`.

```tsx
import { Field, FieldDescription, FieldLabel } from "@zenoxai/ui/components/field"
import { Input } from "@zenoxai/ui/components/input"

function InputFile() {
  return (
    <Field className="max-w-sm">
      <FieldLabel htmlFor="asset-import">Asset inventory</FieldLabel>
      <Input id="asset-import" type="file" accept=".csv" />
      <FieldDescription>
        A CSV file with one hostname or IP per row.
      </FieldDescription>
    </Field>
  )
}
```

## Accessibility

- Every input needs a name: a `FieldLabel` with `htmlFor`, or `aria-label` when the purpose is
  clear from the layout, as in a search box above a table.
- Set `type` (`email`, `url`, `search`, `tel`) and `autoComplete` so mobile keyboards and
  password managers offer the right input.
- The text is 16px below the `md` breakpoint so iOS does not zoom into the field on focus,
  and the 12.5px body size from `md` up.

## API reference

`import { ... } from "@zenoxai/ui/components/input"`

### Input

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| size | `"default" \| "sm" \| "lg"` | `default` | Height: `sm` 28px, `default` 32px, `lg` 36px, the heights of the Button sizes of the same names. Replaces the native `size` attribute (a width in characters); set the width with a class instead. |

