Input

Text or number field with adornments and error states.

import { Input } from 'ui-lab-components/input';
import { Input } from 'ui-lab-components/input';
 
export default function Example() {
  return <Input placeholder="Enter text..." />;
}
 

input/01-basic-input

A simple text input field with default styling. Use this as the standard input element for collecting user text input.

Loading interactive preview
import { Input } from 'ui-lab-components/input';
 
export default function Example() {
  return <Input placeholder="Enter text..." />;
}
 

input/02-validation-states

Input fields with error and success validation states, including helper text for user feedback.

Loading interactive preview
import { Input } from 'ui-lab-components/input'
import { Label } from 'ui-lab-components/label';
import { Icon } from 'ui-lab-components/icon'
 
export default function Example() {
  return (
    <div className="flex flex-col gap-6">
      <div className="flex flex-col gap-1.5">
        <Label error helperText="Please enter a valid email address" helperTextError>
          Email
        </Label>
        <Input
          type="email"
          placeholder="Enter your email"
          error
          defaultValue="invalid-email"
          icon={{ suffix: <Icon id="alert" className="text-danger-600" size={14} /> }}
        />
      </div>
 
      <div className="flex flex-col gap-1.5">
        <Label helperText="Email address is available">
          Email
        </Label>
        <Input
          type="email"
          placeholder="Enter your email"
          defaultValue="user@example.com"
          icon={{ suffix: <Icon id="check-circle" className="text-success-600" size={14} /> }}
          className="border-success-600 focus:border-success-600"
        />
      </div>
 
      <div className="flex flex-col gap-1.5">
        <Label required helperText="We'll never share your email with anyone else.">
          Email
        </Label>
        <Input
          type="email"
          placeholder="Enter your email" />
      </div>
    </div>
  );
}
 

input/03-sign-in-form

Email and password fields with a password visibility toggle — a common authentication pattern.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Button } from 'ui-lab-components/button'
import { Flex } from 'ui-lab-components/flex'
import { Input } from 'ui-lab-components/input';
import { Icon } from 'ui-lab-components/icon'
 
export default function SignInForm() {
  const [showPassword, setShowPassword] = useState(false);
 
  return (
    <Flex direction="column" gap="sm">
      <Input
        type="email"
        icon={<Icon id="mail" size={14} />}
        placeholder="Email address"
        autoComplete="email"
      />
      <Input
        type={showPassword ? 'text' : 'password'}
        icon={<Icon id="lock" size={14} />}
        placeholder="Password"
        autoComplete="current-password"
        actions={[
          {
            icon: showPassword
              ? <Icon id="eye-off" size={14} />
              : <Icon id="eye" size={14} />,
            title: showPassword ? 'Hide password' : 'Show password',
            onClick: () => setShowPassword((value) => !value),
          },
        ]}
      />
      <Button variant="primary" className="w-full mt-1">Sign in</Button>
    </Flex>
  );
}
 

input/05-user-handle

Editable username field with an inline copy action.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Flex } from 'ui-lab-components/flex'
import { Input } from 'ui-lab-components/input';
import { Icon } from 'ui-lab-components/icon';
 
export default function UserHandle() {
  const [handle, setHandle] = useState('kyza');
  const [copied, setCopied] = useState(false);
 
  const handleCopy = () => {
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
 
  return (
    <Flex direction="column" gap="sm">
      <Input
        icon={<Icon id="at" size={14} />}
        placeholder="username"
        value={handle}
        onChange={(event) => setHandle(event.target.value)}
        actions={[
          {
            icon: copied
              ? <Icon id="check" size={14} className="text-green-500" />
              : <Icon id="copy" size={14} />,
            title: copied ? 'Copied!' : 'Copy handle',
            onClick: handleCopy,
          },
        ]}
      />
    </Flex>
  );
}
 

input/06-api-key

Read-only secret field with reveal and copy actions — suitable for credentials and tokens.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Flex } from 'ui-lab-components/flex'
import { Input } from 'ui-lab-components/input';
import { Icon } from 'ui-lab-components/icon';
 
export default function ApiKey() {
  const [revealed, setRevealed] = useState(false);
  const [copied, setCopied] = useState(false);
  const key = 'sk-proj-a8f2c1d9e4b7';
 
  const handleCopy = () => {
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
 
  return (
    <Flex direction="column" gap="sm">
      <Input
        type={revealed ? 'text' : 'password'}
        icon={<Icon id="key" size={14} />}
        value={key}
        readOnly
        actions={[
          {
            icon: revealed
              ? <Icon id="eye-off" size={14} />
              : <Icon id="eye" size={14} />,
            title: revealed ? 'Hide key' : 'Reveal key',
            onClick: () => setRevealed((value) => !value),
          },
          {
            icon: copied
              ? <Icon id="check" size={14} className="text-green-500" />
              : <Icon id="copy" size={14} />,
            title: copied ? 'Copied!' : 'Copy key',
            onClick: handleCopy,
          },
        ]}
      />
    </Flex>
  );
}
 

input/07-url-validation

URL field that shows a success or error icon in the suffix slot based on the input value.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Flex } from 'ui-lab-components/flex'
import { Input } from 'ui-lab-components/input';
import { Icon } from 'ui-lab-components/icon';
 
export default function UrlValidation() {
  const [url, setUrl] = useState('');
 
  const isValid = url.length === 0 || /^https?:\/\/.+\..+/.test(url);
  const showError = url.length > 0 && !isValid;
 
  return (
    <Flex direction="column" gap="sm">
      <Input
        placeholder="https://example.com"
        value={url}
        onChange={(event) => setUrl(event.target.value)}
        error={showError}
        icon={{
          prefix: <Icon id="link" size={14} />,
          suffix: showError
            ? <Icon id="alert" size={14} className="text-red-500" />
            : url.length > 0
              ? <Icon id="check" size={14} className="text-green-500" />
              : undefined,
        }}
      />
    </Flex>
  );
}
 

input/08-quantity

Number input with native spin controls for selecting a bounded quantity.

Loading interactive preview
"use client";
 
import { useState } from 'react';
import { Flex } from 'ui-lab-components/flex'
import { Input } from 'ui-lab-components/input';
 
export default function Quantity() {
  const [qty, setQty] = useState(1);
 
  return (
    <Flex direction="column" gap="sm">
      <Input
        type="number"
        placeholder="Qty"
        value={qty}
        min={1}
        max={99}
        onChange={(event) => setQty(Number(event.target.value))}
      />
    </Flex>
  );
}