• 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.

    Live previewBasic input
    basic.tsx
    import { Input } from '@sudden3/leaf-ui';
    import { Mail, Search } from 'lucide-react';
    
    export function InputBasic() {
      return (
        <div className="leaf-demo-stack">
          <Input aria-label="Project name" placeholder="Name your project" />
          <Input aria-label="Search projects" prefix={<Search />} placeholder="Search projects" />
          <Input aria-label="Email" type="email" prefix={<Mail />} placeholder="hello@leaf.design" />
          <Input aria-label="Read-only project name" defaultValue="Leaf Garden" readOnly />
        </div>
      );
    }
    
    Live previewInteractive example
    Project name is required.
    states.tsx
    import { Input } from '@sudden3/leaf-ui';
    
    export function InputStates() {
      return (
        <div className="leaf-demo-stack">
          <Input aria-label="Disabled input" disabled placeholder="Cannot edit right now" />
          <Input
            aria-label="Project name error"
            status="error"
            placeholder="Enter a project name"
            aria-describedby="project-error"
          />
          <span id="project-error" className="leaf-demo-error">
            Project name is required.
          </span>
          <Input aria-label="Name warning" status="warning" defaultValue="A similar name exists" />
        </div>
      );
    }
    
    Live previewInteractive example
    Submitted:Waiting for input
    controlled.tsx
    import { Input } from '@sudden3/leaf-ui';
    import { useState } from 'react';
    
    export function InputControlled() {
      const [value, setValue] = useState('');
      const [submitted, setSubmitted] = useState('');
      return (
        <div className="leaf-demo-stack">
          <Input
            aria-label="Enter and submit"
            value={value}
            placeholder="Type and press Enter"
            onChange={(event) => setValue(event.target.value)}
            onPressEnter={() => setSubmitted(value)}
          />
          <span className="leaf-demo-note" aria-live="polite">
            Submitted:{submitted || 'Waiting for input'}
          </span>
        </div>
      );
    }
    
    Live previewControl sizes
    sm
    md
    lg
    control-sizes.tsx
    import { Button, type ControlSize, Input, Select } from '@sudden3/leaf-ui';
    
    export function ControlSizes() {
      return (
        <div className="leaf-demo-stack leaf-demo-stack--wide">
          {(['sm', 'md', 'lg'] as const).map((size: ControlSize) => (
            <div key={size} className="leaf-demo-control-row">
              <span className="leaf-demo-size">{size}</span>
              <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: 'In progress', value: 'active' },
                ]}
              />
              <Button size={size}>Search</Button>
            </div>
          ))}
        </div>
      );
    }
    

    Password input

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

    Live previewPassword input
    password.tsx
    import { Input } from '@sudden3/leaf-ui';
    import { Eye, EyeOff, LockKeyhole } from 'lucide-react';
    import { useState } from 'react';
    export function InputPassword() {
      const [visible, setVisible] = useState(false);
      return (
        <div className="leaf-demo-stack">
          <Input
            type="password"
            aria-label="Password"
            placeholder="Enter password"
            autoComplete="new-password"
            prefix={<LockKeyhole />}
          />
          <Input
            type="password"
            aria-label="Controlled password"
            defaultValue="leaf-garden"
            visible={visible}
            onVisibleChange={setVisible}
            visibilityIcon={(shown) => (shown ? <EyeOff size={16} /> : <Eye size={16} />)}
          />
          <Input type="password" aria-label="Disabled password" defaultValue="leaf-garden" disabled />
          <Input
            type="password"
            aria-label="No visibility toggle"
            placeholder="No visibility toggle"
            visibilityToggle={false}
          />
        </div>
      );
    }
    

    Clear and character count

    Live previewClear and character count
    11 / 30
    4 characters

    Current text: Leaf Garden

    clear.tsx
    import { Input } from '@sudden3/leaf-ui';
    import { useState } from 'react';
    export function InputClear() {
      const [value, setValue] = useState('Leaf Garden');
      return (
        <div className="leaf-demo-stack">
          <Input
            aria-label="Project name"
            value={value}
            onChange={(event) => setValue(event.target.value)}
            allowClear
            showCount
            maxLength={30}
          />
          <Input
            aria-label="Keyword"
            defaultValue="Leaf"
            allowClear
            showCount={(text) => `${text.length} characters`}
          />
          <p className="leaf-demo-note">Current text: {value || 'Empty'}</p>
        </div>
      );
    }
    

    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 '@sudden3/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.