Skip to main content

Input Component

** Last Built**: September 2, 2025 at 4:19 PM The Input component is a versatile text input field that provides a consistent interface for user data entry. It supports various input types, validation states, and integrates seamlessly with form systems.

Import

// Input component is available in the live scope

Basic Usage

Live Editor
<Input
  type="text"
  placeholder="Enter your name"
/>
Result
Loading...

Props

PropTypeDefaultDescription
typestring'text'HTML input type (text, email, password, etc.)
valuestring-Current input value
onChange(e: ChangeEvent<HTMLInputElement>) => void-Change handler function
placeholderstring-Placeholder text
disabledbooleanfalseWhether the input is disabled
readOnlybooleanfalseWhether the input is read-only
requiredbooleanfalseWhether the input is required
namestring-Input name attribute
idstring-Input ID attribute
classNamestring-Additional CSS classes
size'sm' | 'md' | 'lg''md'Input size variant
variant'default' | 'error' | 'success''default'Visual state variant
errorstring-Error message to display
helperTextstring-Helper text below the input
leftIconReactNode-Icon to display on the left side
rightIconReactNode-Icon to display on the right side

Input Types

The Input component supports all standard HTML input types:

Live Editor
<div className="space-y-4">
  <Input type="text" placeholder="Enter text" />
  <Input type="email" placeholder="Enter email" />
  <Input type="password" placeholder="Enter password" />
  <Input type="number" placeholder="Enter number" />
  <Input type="search" placeholder="Search..." />
  <Input type="url" placeholder="Enter URL" />
  <Input type="tel" placeholder="Enter phone number" />
</div>
Result
Loading...

Sizes

The Input component comes in three size variants:

Live Editor
<div className="space-y-4">
  <Input size="sm" placeholder="Small input" />
  <Input size="md" placeholder="Medium input (default)" />
  <Input size="lg" placeholder="Large input" />
</div>
Result
Loading...

Variants

Different visual states for different input conditions:

Live Editor
<div className="space-y-4">
  <Input placeholder="Normal input" />
  <Input variant="success" placeholder="Valid input" />
  <Input variant="error" placeholder="Invalid input" error="This field is required" />
</div>
Result
Loading...

With Icons

You can add icons to the left or right side of the input:

import { SearchIcon, EyeIcon, EyeOffIcon } from '@heroicons/react/outline';
// Left icon
<Input
leftIcon={<SearchIcon className="w-5 h-5" />}
placeholder="Search users..."
/>
// Right icon
<Input
type="password"
rightIcon={<EyeIcon className="w-5 h-5" />}
placeholder="Enter password"
/>
// Both icons
<Input
leftIcon={<SearchIcon className="w-5 h-5" />}
rightIcon={<EyeIcon className="w-5 h-5" />}
placeholder="Search with icon"
/>

Form Integration

The Input component works seamlessly with form libraries and validation:

import { useState } from 'react';
function FormExample() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({});
const handleChange = (field, value) => {
setFormData(prev => ({ ...prev, [field]: value }));
// Clear error when user starts typing
if (errors[field]) {
setErrors(prev => ({ ...prev, [field]: '' }));
};
const handleSubmit = (e) => {
e.preventDefault();
// Validation logic here
const newErrors = {};
if (!formData.name) newErrors.name = 'Name is required';
if (!formData.email) newErrors.email = 'Email is required';
if (!formData.password) newErrors.password = 'Password is required';
setErrors(newErrors);
if (Object.keys(newErrors).length === 0) {
// Submit form
console.log('Form submitted:', formData);
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<Input
type="text"
placeholder="Enter your name"
value={formData.name}
onChange={(e) => handleChange('name', e.target.value)}
error={errors.name}
required
/>
</div>
<div>
<Input
type="email"
placeholder="Enter your email"
value={formData.email}
onChange={(e) => handleChange('email', e.target.value)}
error={errors.email}
required
/>
</div>
<div>
<Input
type="password"
placeholder="Enter your password"
value={formData.password}
onChange={(e) => handleChange('password', e.target.value)}
error={errors.password}
required
/>
</div>
<Button type="submit">Submit</Button>
</form>
);
}

Validation States

The Input component provides clear visual feedback for validation states:

function ValidationExample() {
const [email, setEmail] = useState('');
const [isValid, setIsValid] = useState(null);
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleEmailChange = (e) => {
const value = e.target.value;
setEmail(value);
if (value === '') {
setIsValid(null);
} else {
setIsValid(validateEmail(value));
};
return (
<div>
<Input
type="email"
placeholder="Enter email address"
value={email}
onChange={handleEmailChange}
variant={isValid === null ? 'default' : isValid ? 'success' : 'error'}
error={isValid === false ? 'Please enter a valid email address' : ''}
helperText={isValid === true ? 'Email format is valid' : ''}
/>
</div>
);
}

Accessibility

The Input component includes comprehensive accessibility features:

  • Proper ARIA labels and descriptions
  • Error state announcements for screen readers
  • Keyboard navigation support
  • Focus management
  • Screen reader compatibility
<Input
id="username"
name="username"
aria-describedby="username-help username-error"
aria-invalid={!!errors.username}
placeholder="Enter username"
error={errors.username}
helperText="Username must be at least 3 characters long"
/>

Custom Styling

You can customize the appearance using Tailwind CSS classes:

<Input
className="border-2 border-blue-300 focus:border-blue-500 focus:ring-blue-200"
placeholder="Custom styled input"
/>
<Input
className="bg-gray-50 border-gray-300 text-gray-900 placeholder-gray-500"
placeholder="Gray themed input"
/>

Examples

Search Input with Clear Button

function SearchInput() {
const [searchTerm, setSearchTerm] = useState('');
const [showClear, setShowClear] = useState(false);
const handleChange = (e) => {
const value = e.target.value;
setSearchTerm(value);
setShowClear(value.length > 0);
};
const handleClear = () => {
setSearchTerm('');
setShowClear(false);
};
return (
<div className="relative">
<Input
type="search"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
leftIcon={<SearchIcon className="w-5 h-5" />}
rightIcon={
showClear && (
<button
onClick={handleClear}
className="text-gray-400 hover:text-gray-600"
>
<XIcon className="w-5 h-5" />
</button>
)
}
/>
</div>
);
}

Password Input with Toggle

function PasswordInput() {
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
return (
<Input
type={showPassword ? 'text' : 'password'}
placeholder="Enter password"
value={password}
onChange={(e) => setPassword(e.target.value)}
rightIcon={
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="text-gray-400 hover:text-gray-600"
>
{showPassword ? (
<EyeOffIcon className="w-5 h-5" />
) : (
<EyeIcon className="w-5 h-5" />
)}
</button>
}
/>
);
}

Form Field with Label

function FormField({ label, error, helperText, ...inputProps }) {
return (
<div className="space-y-2">
<Label htmlFor={inputProps.id}>{label}</Label>
<Input {...inputProps} />
{helperText && (
<p className="text-sm text-gray-600">{helperText}</p>
)}
{error && (
<p className="text-sm text-red-600">{error}</p>
)}
</div>
);
}
// Usage
<FormField
id="username"
label="Username"
placeholder="Enter username"
helperText="Username must be unique"
error={errors.username}
/>

Best Practices

  1. Always provide labels - Use the Label component or aria-label for accessibility
  2. Use appropriate input types - Leverage HTML5 input types for better UX
  3. Provide clear error messages - Help users understand what went wrong
  4. Use helper text sparingly - Only when additional context is needed
  5. Consider validation timing - Validate on blur or submit, not on every keystroke
  6. Test with screen readers - Ensure all states are properly announced
  • Label - For form field labels
  • Button - For form submission and actions
  • Form - For form containers and validation
  • SelectInput - For dropdown selection
  • DateInput - For date selection