---
title: Input
description: A single-line text field on a control fill with a subtle border.
---

```tsx
import { Input } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function InputBasic() {
  return (
    <Preview stack={true}>
      <Input.Root aria-label="Label" placeholder="Placeholder" />
    </Preview>
  );
}
```

- Wrap an input in a [Field](/deft/components/field) for a visible label, description or error. A bare input needs an `aria-label`.
- The input has the height of a default [Button](/deft/components/button) and [Select](/deft/components/select), so they line up in a row. It takes the full width of its container.
- Use [Textarea](/deft/components/textarea) for text that runs to several lines.
- Use `font="mono"` for DSNs, URLs, slugs and secrets.
- Inside an invalid [Field](/deft/components/field), the input gets a red ring. A disabled input fades and ignores clicks.

## Search

```tsx
import { Input } from "@openperf/deft";
import { IconSearch } from "@tabler/icons-react";

import { Preview } from "../../src/Preview";

export default function InputSearch() {
  return (
    <Preview stack={true}>
      <Input.Root aria-label="Search" icon={IconSearch} placeholder="Search" type="search" />
    </Preview>
  );
}
```

Use one search per page, in the header row. The placeholder names what is searched, such as "Search errors". The browser's clear button is hidden.

## Leading icon and trailing content

```tsx
import { Input } from "@openperf/deft";
import { IconPlus } from "@tabler/icons-react";

import { Preview } from "../../src/Preview";

export default function InputLeadingTrailing() {
  return (
    <Preview stack={true}>
      <Input.Root aria-label="Label" icon={IconPlus} placeholder="Placeholder" />
      <Input.Root
        aria-label="Value"
        defaultValue="12"
        extra={<span className="text-muted">Unit</span>}
      />
    </Preview>
  );
}
```

A leading `icon` explains the value. Use `extra` for compact trailing content such as a unit or a key hint, and leave enough room for the value.

## Prefix

```tsx
import { Input } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function InputPrefix() {
  return (
    <Preview stack={true}>
      <Input.Root aria-label="Label" defaultValue="path" prefix="example.com/" />
    </Preview>
  );
}
```

A `prefix` is fixed muted text right before the value, such as the host in front of a slug. It is part of the field, not of the value.

## Variants

```tsx
import { Input } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function InputVariants() {
  return (
    <Preview stack={true}>
      <Input.Root aria-label="Default" placeholder="Default" />
      <Input.Root aria-label="Field" placeholder="Field" variant="field" />
    </Preview>
  );
}
```

The default sits on a control fill. Use `variant="field"` inside a [List](/deft/components/list), where the field fill keeps the input apart from the inset background.

## API

| Prop | Type | Default | Description |
| - | - | - | - |
| `variant?` | `"default" \| "field"` | `"default"` | |
| `font?` | `"sans" \| "mono"` | `"sans"` | `mono` sets the value and the prefix in the code font. |
| `icon?` | `TablerIcon` | - | Leading icon, in the icon colour. |
| `prefix?` | `ReactNode` | - | Fixed muted text right before the value. |
| `extra?` | `ReactNode` | - | Trailing content inside the field. |
| `render?` | `ReactElement \| function` | - | Replaces the native input element. |

Parts: `Root`. `Root` renders a `label` around the input; `className` styles that wrapper, and other props go to the native `input`. Built on Base UI [Input](https://base-ui.com/react/components/input).
