COMPONENT

Input

A flexible text input component with built-in validation, states, and accessibility features.

Features
  • Native input validation with custom error messages.
  • Supports controlled and uncontrolled modes.
  • Polymorphic component rendering via Necto Primitive.
  • Focus visible styles for keyboard navigation.
  • Automatic aria-invalid handling for validation states.
Example
import { Input } from '@sprocketui/react';

export default function App() {
return <Input placeholder="Enter command..." />;
}
terminal

Usage

The Input component is a flexible, accessible text input with support for various input types and validation states.

Basic Example

import { Input } from '@sprocket-ui/input';
 
<Input
  placeholder="Enter text..."
  onChange={(e) => console.log(e.target.value)}
/>

Input Types

{/* Text input */}
<Input type="text" placeholder="Username" />
 
{/* Email input */}
<Input type="email" placeholder="[email protected]" />
 
{/* Password input */}
<Input type="password" placeholder="Password" />
 
{/* Number input */}
<Input type="number" placeholder="0" min={0} max={100} />
 
{/* Search input */}
<Input type="search" placeholder="Search..." />
 
{/* URL input */}
<Input type="url" placeholder="https://example.com" />
 
{/* Tel input */}
<Input type="tel" placeholder="+1 (555) 000-0000" />

Controlled Input

import { useState } from 'react';
import { Input } from '@sprocket-ui/input';
 
function ControlledExample() {
  const [value, setValue] = useState('');
 
  return (
    <Input
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Controlled input"
    />
  );
}

States

{/* Disabled state */}
<Input isDisabled placeholder="Disabled input" />
 
{/* Read-only state */}
<Input isReadOnly value="Read-only value" />
 
{/* Invalid state */}
<Input isInvalid placeholder="Invalid input" />
 
{/* Required field */}
<Input isRequired placeholder="Required field" />

With Validation

import { useState } from 'react';
import { Input } from '@sprocket-ui/input';
 
function ValidationExample() {
  const [email, setEmail] = useState('');
  const [isInvalid, setIsInvalid] = useState(false);
 
  const validateEmail = (value: string) => {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    setIsInvalid(!emailRegex.test(value) && value.length > 0);
  };
 
  return (
    <div className="flex flex-col gap-1">
      <Input
        type="email"
        value={email}
        onChange={(e) => {
          setEmail(e.target.value);
          validateEmail(e.target.value);
        }}
        isInvalid={isInvalid}
        placeholder="Enter email"
      />
      {isInvalid && (
        <span className="text-sm text-red-500">
          Please enter a valid email address
        </span>
      )}
    </div>
  );
}

With Label

import { Input } from '@sprocket-ui/input';
import { Label } from '@sprocket-ui/label';
 
<div className="flex flex-col gap-2">
  <Label htmlFor="username">Username</Label>
  <Input id="username" placeholder="Enter username" />
</div>
Props(9)
NameTypeDefaultDescription
typeUnionTypei'text'The type of input to render.
valuestringThe current value of the input (controlled mode).
defaultValuestringThe default value of the input (uncontrolled mode).
placeholderstringPlaceholder text shown when the input is empty.
isDisabledbooleanfalseWhether the input is disabled.
isReadOnlybooleanfalseWhether the input is read-only.
isRequiredbooleanfalseWhether the input is required.
isInvalidbooleanfalseWhether the input is in an invalid state.
classNamestringAdditional CSS classes to apply.
Events(3)
NameTypeDescription
onChange(e: ChangeEvent) → voidCalled when the input value changes.
onFocus(e: FocusEvent) → voidCalled when the input receives focus.
onBlur(e: FocusEvent) → voidCalled when the input loses focus.

Accessibility

The Input component follows WAI-ARIA best practices:

  • Uses semantic input element for proper form integration
  • Automatically sets aria-invalid when isInvalid prop is true
  • Automatically sets aria-disabled when isDisabled prop is true
  • Automatically sets aria-readonly when isReadOnly prop is true
  • Automatically sets aria-required when isRequired prop is true
  • Focus management and keyboard navigation work as expected

Styling

The Input component is unstyled by default:

{/* Basic styling */}
<Input
  className="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
  placeholder="Styled input"
/>
 
{/* Invalid state styling */}
<Input
  isInvalid
  className="px-4 py-2 border border-red-500 rounded-lg focus:ring-2 focus:ring-red-500"
  placeholder="Invalid input"
/>
 
{/* Disabled styling */}
<Input
  isDisabled
  className="px-4 py-2 border border-gray-200 rounded-lg bg-gray-100 text-gray-400 cursor-not-allowed"
  placeholder="Disabled input"
/>
Last updated on March 11, 2026

Components