# Input

A text input component for forms and user data entry with built-in styling and accessibility features.

Page: https://sui.draco.dev/docs/components/input

### Example: input-demo

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputDemo() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-demo-api-key`}>
        API Key
      </FieldLabel>
      <Input
        id={`${previewId}-input-demo-api-key`}
        type="password"
        placeholder="sk-..."
      />
      <FieldDescription>
        Your API key is encrypted and stored securely.
      </FieldDescription>
    </Field>
  );
}

export default InputDemo;
```

## Installation

```bash
bunx --bun shadcn@latest add @sui/input
```

Install with the shadcn CLI or use the shared `@workspace/ui` package. Follow the [installation guide](/docs/installation) to configure the registry, load styles, and choose import aliases.

## Usage

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

```tsx
<Input />
```

## Basic

### Example: input-basic

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

export function InputBasic() {
  return <Input placeholder="Enter text" />;
}

export default InputBasic;
```

## Field

Use `Field`, `FieldLabel`, and `FieldDescription` to create an input with a
label and description.

### Example: input-field

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputField() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-field-username`}>
        Username
      </FieldLabel>
      <Input
        id={`${previewId}-input-field-username`}
        type="text"
        placeholder="Enter your username"
      />
      <FieldDescription>
        Choose a unique username for your account.
      </FieldDescription>
    </Field>
  );
}

export default InputField;
```

## Field Group

Use `FieldGroup` to show multiple `Field` blocks and to build forms.

### Example: input-fieldgroup

```tsx
import { Button } from "@workspace/ui/components/button";
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputFieldgroup() {
  const previewId = usePreviewId();

  return (
    <FieldGroup>
      <Field>
        <FieldLabel htmlFor={`${previewId}-fieldgroup-name`}>Name</FieldLabel>
        <Input id={`${previewId}-fieldgroup-name`} placeholder="Jordan Lee" />
      </Field>
      <Field>
        <FieldLabel htmlFor={`${previewId}-fieldgroup-email`}>Email</FieldLabel>
        <Input
          id={`${previewId}-fieldgroup-email`}
          type="email"
          placeholder="name@example.com"
        />
        <FieldDescription>
          We&apos;ll send updates to this address.
        </FieldDescription>
      </Field>
      <Field orientation="horizontal">
        <Button type="reset" variant="outline">
          Reset
        </Button>
        <Button type="submit">Submit</Button>
      </Field>
    </FieldGroup>
  );
}

export default InputFieldgroup;
```

## Disabled

Use the `disabled` prop to disable the input. To style the disabled state, add the `data-disabled` attribute to the `Field` component.

### Example: input-disabled

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputDisabled() {
  const previewId = usePreviewId();

  return (
    <Field data-disabled>
      <FieldLabel htmlFor={`${previewId}-input-demo-disabled`}>
        Email
      </FieldLabel>
      <Input
        id={`${previewId}-input-demo-disabled`}
        type="email"
        placeholder="Email"
        disabled
      />
      <FieldDescription>This field is currently disabled.</FieldDescription>
    </Field>
  );
}

export default InputDisabled;
```

## Invalid

Use the `aria-invalid` prop to mark the input as invalid. To style the invalid state, add the `data-invalid` attribute to the `Field` component.

### Example: input-invalid

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputInvalid() {
  const previewId = usePreviewId();

  return (
    <Field data-invalid>
      <FieldLabel htmlFor={`${previewId}-input-invalid`}>
        Invalid Input
      </FieldLabel>
      <Input
        id={`${previewId}-input-invalid`}
        placeholder="Error"
        aria-invalid
      />
      <FieldDescription>
        This field contains validation errors.
      </FieldDescription>
    </Field>
  );
}

export default InputInvalid;
```

## File

Use the `type="file"` prop to create a file input.

### Example: input-file

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputFile() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-picture`}>Picture</FieldLabel>
      <Input id={`${previewId}-picture`} type="file" />
      <FieldDescription>Select a picture to upload.</FieldDescription>
    </Field>
  );
}

export default InputFile;
```

## Inline

Use `Field` with `orientation="horizontal"` to create an inline input.
Pair with `Button` to create a search input with a button.

### Example: input-inline

```tsx
import { Button } from "@workspace/ui/components/button";
import { Field } from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";

export function InputInline() {
  return (
    <Field orientation="horizontal">
      <Input type="search" placeholder="Search..." />
      <Button>Search</Button>
    </Field>
  );
}

export default InputInline;
```

## Grid

Use a grid layout to place multiple inputs side by side.

### Example: input-grid

```tsx
import { Field, FieldGroup, FieldLabel } from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputGrid() {
  const previewId = usePreviewId();

  return (
    <FieldGroup className="grid max-w-sm grid-cols-2">
      <Field>
        <FieldLabel htmlFor={`${previewId}-first-name`}>First Name</FieldLabel>
        <Input id={`${previewId}-first-name`} placeholder="Jordan" />
      </Field>
      <Field>
        <FieldLabel htmlFor={`${previewId}-last-name`}>Last Name</FieldLabel>
        <Input id={`${previewId}-last-name`} placeholder="Lee" />
      </Field>
    </FieldGroup>
  );
}

export default InputGrid;
```

## Required

Use the `required` attribute to indicate required inputs.

### Example: input-required

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputRequired() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-required`}>
        Required Field <span className="text-destructive">*</span>
      </FieldLabel>
      <Input
        id={`${previewId}-input-required`}
        placeholder="This field is required"
        required
      />
      <FieldDescription>This field must be filled out.</FieldDescription>
    </Field>
  );
}

export default InputRequired;
```

## Badge

Use `Badge` in the label to highlight a recommended field.

### Example: input-badge

```tsx
import { Badge } from "@workspace/ui/components/badge";
import { Field, FieldLabel } from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputBadge() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-badge`}>
        Webhook URL{" "}
        <Badge variant="secondary" className="ml-auto">
          Beta
        </Badge>
      </FieldLabel>
      <Input
        id={`${previewId}-input-badge`}
        type="url"
        placeholder="https://api.example.com/webhook"
      />
    </Field>
  );
}

export default InputBadge;
```

## Input Group

To add icons, text, or buttons inside an input, use the `InputGroup` component. See the [Input Group](/docs/components/input-group) component for more examples.

### Example: input-input-group

```tsx
import { Field, FieldLabel } from "@workspace/ui/components/field";
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@workspace/ui/components/input-group";
import { InfoIcon } from "lucide-react";
import { useId as usePreviewId } from "react";

export function InputInputGroup() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-group-url`}>
        Website URL
      </FieldLabel>
      <InputGroup>
        <InputGroupInput
          id={`${previewId}-input-group-url`}
          placeholder="example.com"
        />
        <InputGroupAddon>
          <InputGroupText>https://</InputGroupText>
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InfoIcon />
        </InputGroupAddon>
      </InputGroup>
    </Field>
  );
}

export default InputInputGroup;
```

## Button Group

To add buttons to an input, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) component for more examples.

### Example: input-button-group

```tsx
import { Button } from "@workspace/ui/components/button";
import { ButtonGroup } from "@workspace/ui/components/button-group";
import { Field, FieldLabel } from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";

export function InputButtonGroup() {
  const previewId = usePreviewId();

  return (
    <Field>
      <FieldLabel htmlFor={`${previewId}-input-button-group`}>
        Search
      </FieldLabel>
      <ButtonGroup>
        <Input
          id={`${previewId}-input-button-group`}
          placeholder="Type to search..."
        />
        <Button variant="outline">Search</Button>
      </ButtonGroup>
    </Field>
  );
}

export default InputButtonGroup;
```

## Form

A full form example with multiple inputs, a select, and a button.

### Example: input-form

```tsx
import { Button } from "@workspace/ui/components/button";
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@workspace/ui/components/select";
import { useId as usePreviewId } from "react";

export function InputForm() {
  const previewId = usePreviewId();

  const countries = [
    { label: "United States", value: "us" },
    { label: "United Kingdom", value: "uk" },
    { label: "Canada", value: "ca" },
  ];
  return (
    <form className="w-full max-w-sm">
      <FieldGroup>
        <Field>
          <FieldLabel htmlFor={`${previewId}-form-name`}>Name</FieldLabel>
          <Input
            id={`${previewId}-form-name`}
            type="text"
            placeholder="Evil Rabbit"
            required
          />
        </Field>
        <Field>
          <FieldLabel htmlFor={`${previewId}-form-email`}>Email</FieldLabel>
          <Input
            id={`${previewId}-form-email`}
            type="email"
            placeholder="john@example.com"
          />
          <FieldDescription>
            We&apos;ll never share your email with anyone.
          </FieldDescription>
        </Field>
        <div className="grid grid-cols-2 gap-4">
          <Field>
            <FieldLabel htmlFor={`${previewId}-form-phone`}>Phone</FieldLabel>
            <Input
              id={`${previewId}-form-phone`}
              type="tel"
              placeholder="+1 (555) 123-4567"
            />
          </Field>
          <Field>
            <FieldLabel htmlFor={`${previewId}-form-country`}>
              Country
            </FieldLabel>
            <Select items={countries} defaultValue="us">
              <SelectTrigger id={`${previewId}-form-country`}>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectGroup>
                  {countries.map((country) => (
                    <SelectItem key={country.value} value={country.value}>
                      {country.label}
                    </SelectItem>
                  ))}
                </SelectGroup>
              </SelectContent>
            </Select>
          </Field>
        </div>
        <Field>
          <FieldLabel htmlFor={`${previewId}-form-address`}>Address</FieldLabel>
          <Input
            id={`${previewId}-form-address`}
            type="text"
            placeholder="123 Main St"
          />
        </Field>
        <Field orientation="horizontal">
          <Button type="button" variant="outline">
            Cancel
          </Button>
          <Button type="submit">Submit</Button>
        </Field>
      </FieldGroup>
    </form>
  );
}

export default InputForm;
```

## RTL

To enable RTL support in shadcn/ui, see the [RTL configuration guide](https://ui.shadcn.com/docs/rtl).

### Example: input-rtl

```tsx
"use client";

import {
  Field,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import { Input } from "@workspace/ui/components/input";
import { useId as usePreviewId } from "react";
import { type Translations, useTranslation } from "./support";

const translations: Translations = {
  en: {
    dir: "ltr",
    values: {
      apiKey: "API Key",
      placeholder: "sk-...",
      description: "Your API key is encrypted and stored securely.",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      apiKey: "مفتاح API",
      placeholder: "sk-...",
      description: "مفتاح API الخاص بك مشفر ومخزن بأمان.",
    },
  },
  he: {
    dir: "rtl",
    values: {
      apiKey: "מפתח API",
      placeholder: "sk-...",
      description: "מפתח ה-API שלך מוצפן ונשמר בצורה מאובטחת.",
    },
  },
};

export function InputRtl() {
  const previewId = usePreviewId();

  const { dir, t } = useTranslation(translations, "ar");

  return (
    <Field dir={dir}>
      <FieldLabel htmlFor={`${previewId}-input-rtl-api-key`}>
        {t.apiKey}
      </FieldLabel>
      <Input
        id={`${previewId}-input-rtl-api-key`}
        type="password"
        placeholder={t.placeholder}
        dir={dir}
      />
      <FieldDescription>{t.description}</FieldDescription>
    </Field>
  );
}

export default InputRtl;
```
