> Leaf UI 0.6.0 · Package: @ifhover/leaf-ui · Source: b30c3d3a8fa9c5e15d0d0522cebfbd33f60c6b06
> Browser documentation: https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/input.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms-full.txt.

# Input

Enter a single line of text.

## Examples

Use controlled value / onChange or uncontrolled defaultValue. Prefix and suffix are decorative content. Standard name, required, type, form and aria-\* properties are forwarded to the input; className and style apply to the container.


Project name

Search projects

Email

Read-only project name

basic.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/basic.tsx"
import { Form, FormField, Input } from '@ifhover/leaf-ui';

import { Mail, Search } from 'lucide-react';

export function InputBasic() {
  return (
    <Form layout="vertical">
      <FormField label="Project name">
        <Input aria-label="Project name" placeholder="Name your project" />
      </FormField>
      <FormField label="Search projects">
        <Input aria-label="Search projects" prefix={<Search />} placeholder="Search projects" />
      </FormField>
      <FormField label="Email">
        <Input aria-label="Email" type="email" prefix={<Mail />} placeholder="hello@leaf.design" />
      </FormField>
      <FormField label="Read-only project name">
        <Input aria-label="Read-only project name" defaultValue="Leaf Garden" readOnly />
      </FormField>
    </Form>
  );
}
```

Expand code


Disabled input

Project name error

Project name is required.

Name warning

states.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/states.tsx"
import { Form, FormField, Input } from '@ifhover/leaf-ui';

export function InputStates() {
  return (
    <Form layout="vertical" onSubmit={(event) => event.preventDefault()}>
      <FormField label="Disabled input">
        <Input disabled placeholder="Currently unavailable" />
      </FormField>
      <FormField label="Project name error" error="Project name is required.">
        <Input placeholder="Enter a project name" />
      </FormField>
      <FormField label="Name warning">
        <Input status="warning" defaultValue="A similar name already exists" />
      </FormField>
    </Form>
  );
}
```

Expand code


Enter and submit

Submitted:Waiting for input

controlled.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/controlled.tsx"
import { Form, FormField, Input, Text } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function InputControlled() {
  const [value, setValue] = useState('');
  const [submitted, setSubmitted] = useState('');
  return (
    <Form layout="vertical">
      <FormField label="Enter and submit">
        <Input
          aria-label="Enter and submit"
          value={value}
          placeholder="Type and press Enter"
          onChange={(event) => setValue(event.target.value)}
          onPressEnter={() => setSubmitted(value)}
        />
      </FormField>
      <Text tone="muted" aria-live="polite">
        Submitted:{submitted || 'Waiting for input'}
      </Text>
    </Form>
  );
}
```

Expand code


smSearch

mdSearch

lgSearch

control-sizes.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/guide/control-sizes.tsx"
import type { ControlSize } from '@ifhover/leaf-ui';

import { Button, Flex, Input, Select, Text } from '@ifhover/leaf-ui';

export function ControlSizes() {
  return (
    <Flex direction="column" gap="md">
      {(['sm', 'md', 'lg'] as const).map((size: ControlSize) => (
        <Flex key={size} align="center" gap="sm" wrap>
          <Text tone="muted">{size}</Text>
          <Input size={size} aria-label={`${size} search`} placeholder="Search projects" />
          <Select
            size={size}
            aria-label={`${size} status`}
            defaultValue="all"
            options={[
              { label: 'All statuses', value: 'all' },
              { label: 'Active', value: 'active' },
            ]}
          />
          <Button size={size}>Search</Button>
        </Flex>
      ))}
    </Flex>
  );
}
```

Expand code

## Password input

Use type="password" to mask input and show a visibility toggle. Customize the icon or hide the toggle when needed.


Password

Controlled password

Disabled password

No visibility toggle

password.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/password.tsx"
import { Form, FormField, Input } from '@ifhover/leaf-ui';

import { Eye, EyeOff, LockKeyhole } from 'lucide-react';

import { useState } from 'react';

export function InputPassword() {
  const [visible, setVisible] = useState(false);
  return (
    <Form layout="vertical">
      <FormField label="Password">
        <Input
          type="password"
          aria-label="Password"
          placeholder="Enter password"
          autoComplete="new-password"
          prefix={<LockKeyhole />}
        />
      </FormField>
      <FormField label="Controlled password">
        <Input
          type="password"
          aria-label="Controlled password"
          defaultValue="leaf-garden"
          visible={visible}
          onVisibleChange={setVisible}
          visibilityIcon={(shown) => (shown ? <EyeOff size={16} /> : <Eye size={16} />)}
        />
      </FormField>
      <FormField label="Disabled password">
        <Input type="password" aria-label="Disabled password" defaultValue="leaf-garden" disabled />
      </FormField>
      <FormField label="No visibility toggle">
        <Input
          type="password"
          aria-label="No visibility toggle"
          placeholder="No visibility toggle"
          visibilityToggle={false}
        />
      </FormField>
    </Form>
  );
}
```

Expand code

## Clear and character count


Project name

11 / 30

Keyword

4 characters

Current text: Leaf Garden

clear.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/clear.tsx"
import { Form, FormField, Input, Text } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function InputClear() {
  const [value, setValue] = useState('Leaf Garden');
  return (
    <Form layout="vertical">
      <FormField label="Project name">
        <Input
          aria-label="Project name"
          value={value}
          onChange={(event) => setValue(event.target.value)}
          allowClear
          showCount
          maxLength={30}
        />
      </FormField>
      <FormField label="Keyword">
        <Input
          aria-label="Keyword"
          defaultValue="Leaf"
          allowClear
          showCount={(text) => `${text.length} characters`}
        />
      </FormField>
      <Text tone="muted">Current text: {value || 'Empty'}</Text>
    </Form>
  );
}
```

Expand code

## Extended features


SearchSearch

Search: No search yet

Input group

extensions.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/input/extensions.tsx"
import { Flex, Input, InputGroup, InputSearch, Select, Space, Text } from '@ifhover/leaf-ui';

import { useState } from 'react';

export function ExtensionDemo() {
  const [query, setQuery] = useState('');
  return (
    <Space direction="vertical" align="stretch">
      <label htmlFor="input-extension-1">
        Search
        <InputSearch
          id="input-extension-1"
          placeholder="Search projects"
          enterButton="Search"
          onSearch={setQuery}
        />
      </label>
      <p role="status">Search: {query || 'No search yet'}</p>
      <Flex direction="column" gap="sm" align="center">
        <Text>Input group</Text>
        <InputGroup aria-label="URL">
          <Select
            style={{ width: 110 }}
            defaultValue="https"
            options={[{ value: 'https', label: 'https://' }]}
          />
          <Input aria-label="Domain" placeholder="example.com" />
        </InputGroup>
      </Flex>
    </Space>
  );
}
```

Expand code

## Input API

| Property                     | Type                                                            | Default  | Description                                   |
| ---------------------------- | --------------------------------------------------------------- | -------- | --------------------------------------------- |
| `size`                       | `'sm' \| 'md' \| 'lg'`                                          | `'md'`   | Control size                                  |
| `status`                     | `'error' \| 'warning'`                                          | —        | Validation appearance                         |
| `prefix` / `suffix`          | `ReactNode`                                                     | —        | Decorative content before / after the input   |
| `onPressEnter`               | `KeyboardEventHandler<HTMLInputElement>`                        | —        | Runs when Enter is pressed                    |
| `type`                       | `HTMLInputTypeAttribute`                                        | `'text'` | Input type; use `'password'` for passwords    |
| `visibilityToggle`           | `boolean`                                                       | `true`   | Show the password visibility toggle           |
| `visible` / `defaultVisible` | `boolean`                                                       | `false`  | Controlled / initial password visibility      |
| `onVisibleChange`            | `(visible: boolean) => void`                                    | —        | Password visibility change                    |
| `visibilityIcon`             | `(visible: boolean) => ReactNode`                               | —        | Custom visibility toggle icon                 |
| `value` / `defaultValue`     | `string \| number \| readonly string[]`                         | —        | Controlled value / initial uncontrolled value |
| `onChange`                   | `ChangeEventHandler<HTMLInputElement>`                          | —        | Read event.target.value                       |
| `disabled` / `readOnly`      | `boolean`                                                       | `false`  | Disabled / read-only                          |
| `ref`                        | `Ref<HTMLInputElement>`                                         | —        | DOM reference                                 |
| `allowClear`                 | `boolean`                                                       | `false`  | Show clear button                             |
| `onClear`                    | `() => void`                                                    | —        | After clearing; onChange also fires           |
| `showCount`                  | `boolean \| ((value: string, maxLength?: number) => ReactNode)` | `false`  | Show or customize the character count         |

## Types

Import InputProps to describe component props. Option types in the API table link to their detailed fields above.

```ts
import type { InputProps } from '@ifhover/leaf-ui';
```

## Forms and localization

Use name to include values in FormData. Uncontrolled fields follow form reset; reset controlled values in application state. Place controls in [FormField](https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/form.md#formfield-api) for labels, help and errors. [ConfigProvider](https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/config-provider.md) supplies regional themes and translated built-in UI. Application labels and options are your responsibility.

## Extension types

```ts
import type { InputSearchProps, InputGroupProps } from '@ifhover/leaf-ui';
```

## InputSearchProps API

| Property           | Type                                                            | Default | Description                                |
| ------------------ | --------------------------------------------------------------- | ------- | ------------------------------------------ |
| `size`             | `'sm' \| 'md' \| 'lg'`                                          | `'md'`  | Size or spacing preset                     |
| `status`           | `'error' \| 'warning'`                                          | —       | Display state                              |
| `prefix`           | `ReactNode`                                                     | —       | Content before the input                   |
| `suffix`           | `ReactNode`                                                     | —       | Content after the input                    |
| `allowClear`       | `boolean`                                                       | `false` | Show the clear button                      |
| `onClear`          | `() => void`                                                    | —       | Called after clearing the input            |
| `showCount`        | `boolean \| ((value: string, maxLength?: number) => ReactNode)` | `false` | Display count or a custom renderer         |
| `visibilityToggle` | `boolean`                                                       | `true`  | Show the password visibility toggle        |
| `visible`          | `boolean`                                                       | —       | Controlled password visibility             |
| `defaultVisible`   | `boolean`                                                       | `false` | Initial password visibility                |
| `onVisibleChange`  | `(visible: boolean) => void`                                    | —       | Password visibility change                 |
| `visibilityIcon`   | `(visible: boolean) => ReactNode`                               | —       | Custom password visibility icon            |
| `onPressEnter`     | `KeyboardEventHandler<HTMLInputElement>`                        | —       | Called when Enter is pressed               |
| `onSearch`         | `(value: string) => void`                                       | —       | Search or Enter callback                   |
| `loading`          | `boolean`                                                       | `false` | Loading state                              |
| `enterButton`      | `ReactNode`                                                     | —       | Search button label; omitted shows an icon |

## InputGroupProps API

| Property  | Type      | Default | Description            |
| --------- | --------- | ------- | ---------------------- |
| `compact` | `boolean` | —       | Join adjacent controls |
