---
title: Input
description: Text input component with icon slots, loading state, and form field integration.
sidebar:
  order: 3
search:
  tags: [text field, textbox, form control, loading]
---

# Input

> Text input component with icon slots, loading state, and form field integration.

## Import

```tsx
import { Input } from 'moraine'
```

## Slot Structure

Text input shell with optional leading and trailing icon slots.

```text
root
├── leading (optional)
├── input
└── trailing (optional)
```

## Examples

### Variants

Visual style variants.

```tsx
function InputVariants() {
  const VARIANTS = ['outline', 'subtle', 'ghost', 'none'] as const

  return (
    <div class="gap-3 grid lg:grid-cols-3 sm:grid-cols-2">
      <For each={VARIANTS}>{(variant) => <Input variant={variant} placeholder={variant} />}</For>
    </div>
  )
}
```

### Sizes

From xs to xl.

```tsx
function InputSizes() {
  const SIZES = ['xs', 'sm', 'md', 'lg', 'xl'] as const

  return (
    <div class="gap-3 grid lg:grid-cols-3 sm:grid-cols-2">
      <For each={SIZES}>{(size) => <Input size={size} placeholder={`Size: ${size}`} />}</For>
    </div>
  )
}
```

### With Icons

Leading and trailing icon slots.

```tsx
function InputWithIcons() {
  return (
    <div class="gap-3 grid sm:grid-cols-2">
      <Input
        leading="i-lucide-search"
        placeholder="Search..."
        classes={{ leading: 'bg-muted p-3' }}
      />
      <Input leading="i-lucide-mail" trailing="i-lucide-check" placeholder="Email" />
      <Input
        trailing={<span class="text-xs text-muted-foreground/80">.com</span>}
        placeholder="Domain"
      />
      <Input
        leading={
          <div class="text-muted-foreground flex gap-1 items-center">
            <Icon name="i-lucide-globe" />
            https://
          </div>
        }
        placeholder="website.com"
        classes={{
          input: 'ps-0',
        }}
      />
    </div>
  )
}
```

### States

Loading, disabled, and type.

```tsx
function InputStates() {
  return (
    <div class="gap-3 grid sm:grid-cols-2">
      <Input loading placeholder="Loading..." />
      <Input disabled placeholder="Disabled" value="Cannot edit" />
      <Input type="file" />
      <Input type="datetime-local" />
    </div>
  )
}
```

## API Reference

### Attributes

#### `root`

Input wrapper that positions icons, loading state, and the native input.

#### `input`

Native text input element.

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |

#### `leading`

Icon or loading indicator rendered before the input value.

#### `trailing`

Icon or loading indicator rendered after the input value.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| autocomplete | JSX.InputHTMLAttributes<HTMLInputElement>["autocomplete"] \| undefined | off | The autocomplete attribute for the input. |
| autofocus | boolean \| undefined | false | Whether the input should automatically receive focus on mount. |
| autofocusDelay | number \| undefined | 0 | The delay in milliseconds before automatically focusing the input. |
| children | JSX.Element | — | Additional content to render inside the input container. |
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | InputT.Classes \| undefined | — | — |
| defaultValue | InputT.Value | — | The default value of the input (uncontrolled). |
| disabled | boolean \| undefined | false | Whether the input is disabled. |
| id | string \| undefined | — | The ID of the input element. |
| leading | IconT.Name | — | Leading icon name. |
| loading | boolean \| undefined | false | Whether the input is in a loading state. |
| loadingIcon | IconT.Name | icon-loading | The icon to show when the input is in a loading state. |
| maxLength | string \| number \| undefined | — | The maximum number of characters allowed in the input. |
| modelModifiers | M \| undefined | — | Modifiers for the input value (e.g., trim, lazy, number). |
| name | string \| undefined | — | The name of the input element, used for form submission. |
| onBlur | JSX.FocusEventHandlerUnion<HTMLInputElement, FocusEvent> \| undefined | — | Event handler for the blur event. |
| onChange | ((value: ModifierValue<M>) => void) \| undefined | — | Callback when the input value change is committed. |
| onFocus | JSX.FocusEventHandlerUnion<HTMLInputElement, FocusEvent> \| undefined | — | Event handler for the focus event. |
| onInput | JSX.InputEventHandlerUnion<HTMLInputElement, InputEvent> \| undefined | — | Event handler for the input event. |
| onValueChange | ((value: ModifierValue<M>) => void) \| undefined | — | Callback when the input value changes during input. |
| placeholder | string \| undefined | — | The placeholder text for the input. |
| readOnly | boolean \| undefined | false | Whether the input is read-only. |
| ref | JSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never \| undefined | — | — |
| required | boolean \| undefined | false | Whether the input is required. |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" \| undefined | — | — |
| style | JSX.CSSProperties \| undefined | — | — |
| styles | InputT.Styles \| undefined | — | — |
| trailing | IconT.Name | — | Trailing icon name. |
| type | JSX.InputHTMLAttributes<HTMLInputElement>["type"] \| undefined | text | The type of the input element. |
| value | InputT.Value | — | The current value of the input (controlled). |
| variant | "none" \| "outline" \| "ghost" \| "subtle" \| undefined | — | — |

### ARIA

Accessibility attributes and roles emitted by the component markup.

| Attribute | Type | Description |
| --- | --- | --- |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-hidden | boolean \| string \| undefined | Hides decorative content from assistive technology. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |

### Data Attributes

State and slot attributes exposed for styling hooks and selectors.

| Attribute | Type | Description |
| --- | --- | --- |
| data-slot | string | Identifies the rendered slot for styling hooks and selectors. |
