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, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/input.md.
  • English
  • 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.

    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>
      );
    }
    
    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>
      );
    }
    
    Submitted:Waiting for 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>
      );
    }
    
    sm
    md
    lg
    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>
      );
    }
    

    Password input

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

    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>
      );
    }
    

    Clear and character count

    11 / 30
    4 characters
    Current text: Leaf Garden
    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>
      );
    }
    

    Extended features

    Search: No search yet

    Input group
    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>
      );
    }
    

    Input API

    PropertyTypeDefaultDescription
    size'sm' | 'md' | 'lg''md'Control size
    status'error' | 'warning'—Validation appearance
    prefix / suffixReactNode—Decorative content before / after the input
    onPressEnterKeyboardEventHandler<HTMLInputElement>—Runs when Enter is pressed
    typeHTMLInputTypeAttribute'text'Input type; use 'password' for passwords
    visibilityTogglebooleantrueShow the password visibility toggle
    visible / defaultVisiblebooleanfalseControlled / initial password visibility
    onVisibleChange(visible: boolean) => void—Password visibility change
    visibilityIcon(visible: boolean) => ReactNode—Custom visibility toggle icon
    value / defaultValuestring | number | readonly string[]—Controlled value / initial uncontrolled value
    onChangeChangeEventHandler<HTMLInputElement>—Read event.target.value
    disabled / readOnlybooleanfalseDisabled / read-only
    refRef<HTMLInputElement>—DOM reference
    allowClearbooleanfalseShow clear button
    onClear() => void—After clearing; onChange also fires
    showCountboolean | ((value: string, maxLength?: number) => ReactNode)falseShow or customize the character count

    Types

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

    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 for labels, help and errors. ConfigProvider supplies regional themes and translated built-in UI. Application labels and options are your responsibility.

    Extension types

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

    InputSearchProps API

    PropertyTypeDefaultDescription
    size'sm' | 'md' | 'lg''md'Size or spacing preset
    status'error' | 'warning'—Display state
    prefixReactNode—Content before the input
    suffixReactNode—Content after the input
    allowClearbooleanfalseShow the clear button
    onClear() => void—Called after clearing the input
    showCountboolean | ((value: string, maxLength?: number) => ReactNode)falseDisplay count or a custom renderer
    visibilityTogglebooleantrueShow the password visibility toggle
    visibleboolean—Controlled password visibility
    defaultVisiblebooleanfalseInitial password visibility
    onVisibleChange(visible: boolean) => void—Password visibility change
    visibilityIcon(visible: boolean) => ReactNode—Custom password visibility icon
    onPressEnterKeyboardEventHandler<HTMLInputElement>—Called when Enter is pressed
    onSearch(value: string) => void—Search or Enter callback
    loadingbooleanfalseLoading state
    enterButtonReactNode—Search button label; omitted shows an icon

    InputGroupProps API

    PropertyTypeDefaultDescription
    compactboolean—Join adjacent controls