Skip to content

Input

Input

A flexible text input component with validation states, icons, and extensive customization options.

Import

import { Input } from '@primitivekit/react';

Basic Usage

<Input 
  label="Email" 
  placeholder="Enter your email"
  type="email"
/>

Variants

The Input component supports multiple visual styles:

// Default variant
<Input variant="default" placeholder="Default input" />

// Filled variant
<Input variant="filled" placeholder="Filled input" />

// Flushed variant (bottom border only)
<Input variant="flushed" placeholder="Flushed input" />

// Unstyled variant
<Input variant="unstyled" placeholder="Unstyled input" />

Sizes

<Input size="small" placeholder="Small input" />
<Input size="medium" placeholder="Medium input" />
<Input size="large" placeholder="Large input" />

Validation States

// Error state
<Input 
  label="Email"
  error="Invalid email address"
  value="invalid-email"
/>

// Success state
<Input 
  label="Username"
  success="Username is available"
  value="john_doe"
/>

// Warning state
<Input 
  label="Password"
  warning="Password strength: weak"
  type="password"
/>

With Icons

import { SearchIcon, LockIcon } from 'your-icon-library';

// Left icon
<Input 
  placeholder="Search..."
  leftElement={<SearchIcon />}
/>

// Right icon
<Input 
  type="password"
  placeholder="Enter password"
  rightElement={<LockIcon />}
/>

// Both icons
<Input 
  placeholder="Search securely"
  leftElement={<SearchIcon />}
  rightElement={<LockIcon />}
/>

Helper Text

<Input 
  label="Username"
  helperText="Choose a unique username"
  placeholder="Enter username"
/>

Full Width

<Input 
  label="Full Name"
  fullWidth
  placeholder="Enter your full name"
/>

Disabled & Read-Only

// Disabled
<Input 
  label="Disabled Input"
  disabled
  value="Cannot edit"
/>

// Read-only
<Input 
  label="Read-only Input"
  readOnly
  value="Can select but not edit"
/>

Input Types

<Input type="text" placeholder="Text" />
<Input type="email" placeholder="Email" />
<Input type="password" placeholder="Password" />
<Input type="number" placeholder="Number" />
<Input type="tel" placeholder="Phone" />
<Input type="url" placeholder="URL" />
<Input type="search" placeholder="Search" />
<Input type="date" />
<Input type="time" />
<Input type="datetime-local" />

Controlled Input

import { useState } from 'react';

function ControlledInput() {
  const [value, setValue] = useState('');

  return (
    <Input
      label="Controlled Input"
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Type something..."
    />
  );
}

Props

PropTypeDefaultDescription
size'small' | 'medium' | 'large''medium'Input size
variant'default' | 'filled' | 'flushed' | 'unstyled''default'Visual style variant
state'default' | 'error' | 'success' | 'warning''default'Validation state
labelstring-Label text
helperTextstring-Helper text below input
errorstring-Error message (sets state to ’error')
successstring-Success message (sets state to ‘success’)
warningstring-Warning message (sets state to ‘warning’)
fullWidthbooleanfalseMake input full width
leftElementReactNode-Icon or element on the left
rightElementReactNode-Icon or element on the right
typestring'text'HTML input type
placeholderstring-Placeholder text
valuestring | number-Controlled value
defaultValuestring | number-Uncontrolled default value
onChangefunction-Change handler
onFocusfunction-Focus handler
onBlurfunction-Blur handler
disabledbooleanfalseDisable input
readOnlybooleanfalseMake read-only
requiredbooleanfalseMark as required
classNamestring-Additional CSS classes
styleInputCSSVariables-CSS variable overrides

Customization

CSS Variables

The Input component supports 100+ CSS variables for complete customization:

<Input
  placeholder="Custom input"
  style={{
    '--input-bg-color': 'rgba(240, 240, 255, 1)',
    '--input-text-color': 'rgba(0, 0, 100, 1)',
    '--input-border-color': 'rgba(100, 100, 200, 1)',
    '--input-border-radius': '12px',
    '--input-padding-x': '16px',
    '--input-padding-y': '12px',
    '--input-font-size': '16px',
    '--input-border-color-focus': 'rgba(0, 100, 255, 1)',
    '--input-ring-color': 'rgba(0, 100, 255, 0.2)',
  }}
/>

Global Customization

:root {
  /* Base colors */
  --input-bg-color: rgba(255, 255, 255, 1);
  --input-text-color: rgba(0, 0, 0, 1);
  --input-border-color: rgba(200, 200, 200, 1);
  
  /* Focus state */
  --input-border-color-focus: rgba(0, 100, 255, 1);
  --input-ring-color: rgba(0, 100, 255, 0.2);
  --input-ring-width: 3px;
  
  /* Spacing */
  --input-padding-x: 12px;
  --input-padding-y: 8px;
  --input-border-radius: 8px;
  
  /* Typography */
  --input-font-size: 14px;
  --input-font-weight: 400;
  
  /* States */
  --input-border-color-error: rgba(255, 0, 0, 1);
  --input-border-color-success: rgba(0, 200, 0, 1);
  --input-border-color-warning: rgba(255, 150, 0, 1);
}

Accessibility

The Input component is fully accessible:

  • ✅ Proper label association with htmlFor and id
  • ✅ ARIA attributes for validation states
  • ✅ Keyboard navigation support
  • ✅ Screen reader announcements for errors
  • ✅ Focus visible indicators
  • ✅ Touch target size (44x44px minimum)

ARIA Attributes

<Input
  label="Email"
  ariaLabel="Email address"
  ariaDescribedBy="email-helper"
  ariaInvalid={hasError}
  required
/>

Examples

Login Form

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  return (
    <form>
      <Input
        label="Email"
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Enter your email"
        required
        fullWidth
      />
      
      <Input
        label="Password"
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Enter your password"
        required
        fullWidth
      />
    </form>
  );
}

Search Input

import { SearchIcon } from 'your-icon-library';

function SearchInput() {
  const [query, setQuery] = useState('');

  return (
    <Input
      type="search"
      placeholder="Search..."
      value={query}
      onChange={(e) => setQuery(e.target.value)}
      leftElement={<SearchIcon />}
      variant="filled"
      fullWidth
    />
  );
}

Validated Input

function ValidatedInput() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const validateEmail = (value: string) => {
    if (!value) {
      setError('Email is required');
    } else if (!/\S+@\S+\.\S+/.test(value)) {
      setError('Invalid email format');
    } else {
      setError('');
    }
  };

  return (
    <Input
      label="Email"
      type="email"
      value={email}
      onChange={(e) => {
        setEmail(e.target.value);
        validateEmail(e.target.value);
      }}
      error={error}
      placeholder="Enter your email"
    />
  );
}

Related Components

  • Textarea - Multi-line text input
  • Select - Dropdown selection
  • Form - Form wrapper with validation