Input
A flexible text input component for forms. Supports labels, hints, icons, validation states, and multiple sizes. Available as compound components for maximum flexibility or as a pre-composed TextInput for simple use cases.
Basic Usage
import { TextInput } from '@/components'
<TextInput placeholder="Enter your name..." />With Label and Hint
Add a label and helper text to guide users.
<TextInput
label="Email Address"
placeholder="john@example.com"
hint="We'll never share your email with anyone."
/>We'll never share your email with anyone.
Sizes
The input comes in three sizes: small (36px), medium (40px, default), and large (44px).
Small (36px)
Medium (40px) - Default
Large (44px)
Small
<TextInput size="sm" label="Small Input" placeholder="Small size..." />Medium (Default)
<TextInput size="md" label="Medium Input" placeholder="Medium size..." />Large
<TextInput size="lg" label="Large Input" placeholder="Large size..." />States
The input has multiple visual states: Default (idle), Hover, Focus, Filled, Disabled, and Error.
Default (Idle)
Filled
Focus (click to focus)
Required Fields
Use the required prop to show a required indicator (blue asterisk).
<TextInput
label="Username"
placeholder="Enter username..."
hint="This field is required"
required
/>This field is required
Optional Fields
Use showOptionalBadge to indicate optional fields.
<TextInput
label="Nickname"
placeholder="Enter nickname..."
showOptionalBadge
/>This field is optional
With Tooltip
Add a tooltip to the info icon to provide additional context without cluttering the UI. The info icon automatically appears when a tooltip prop is provided.
<TextInput
label="API Key"
placeholder="Enter your API key..."
hint="Keep your API key secure"
tooltip="Your API key is used to authenticate requests to the server. Never share it publicly."
/>Keep your API key secure
Keep your API key secure
With Icons
Add icons to the left and/or right of the input.
Left icon
Right icon
Both icons
Left Icon
<TextInput
label="Username"
placeholder="Enter username..."
leftIcon={<User />}
/>Right Icon
<TextInput
label="Search"
placeholder="Search..."
rightIcon={<Search />}
/>Both Icons
<TextInput
label="Email"
placeholder="Search contacts..."
leftIcon={<Mail />}
rightIcon={<Search />}
/>Keyboard Shortcut Badge
Display a keyboard shortcut badge inside the input.
<TextInput
label="Quick Search"
placeholder="Search..."
leftIcon={<Search />}
kbd="⌘+K"
/>Error State
Show validation errors with the error prop. Pass a string to display an error message, or true for styling only.
Error with message
Please enter a valid email address
Error styling only
Password must be at least 8 characters
Error with Message
<TextInput
label="Email"
placeholder="Enter email..."
error="Please enter a valid email address"
/>Error Styling Only
<TextInput
label="Password"
type="password"
error
hint="Password must be at least 8 characters"
/>Disabled State
Disabled inputs cannot be interacted with.
Disabled empty
Disabled with value
<TextInput label="Disabled" placeholder="Cannot edit..." disabled />Compound Components
For maximum flexibility, use the compound component API to build custom input layouts.
import { Input } from '@/components'
<Input.Root size="md" required>
<Input.Label>
Full Name
<Input.RequiredIndicator />
<Input.InfoIcon />
</Input.Label>
<Input.Field>
<Input.LeftSlot>
<User />
</Input.LeftSlot>
<Input.NativeInput placeholder="Enter your full name..." />
</Input.Field>
<Input.Hint>Please enter your legal name.</Input.Hint>
</Input.Root>Please enter your legal name as it appears on documents.
Password Input
A convenience wrapper for password inputs with built-in visibility toggle and lock icon.
import { PasswordInput } from '@/components'
<PasswordInput label="Password" placeholder="Enter password..." />Password Input Sizes
Small (36px)
Medium (40px) - Default
Large (44px)
Password Input States
Default
With hint
Must be at least 8 characters
Error
Password is too weak
Disabled
Without Lock Icon
Hide the lock icon with showLeftIcon={false}.
<PasswordInput label="Password" showLeftIcon={false} />With Password Strength Indicator
Compose PasswordInput with PasswordStrength for password creation forms.
const [password, setPassword] = useState('')
const passedCount = defaultRequirements.filter((req) => req.validator(password)).length
const isComplete = passedCount === defaultRequirements.length
<PasswordInput
label="Create Password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
error={password.length > 0 && !isComplete}
/>
<PasswordStrength password={password} />Must contain at least;
Advanced: Compound Components
For maximum flexibility, use the compound component API to build custom password input layouts.
Must be at least 8 characters
const [showPassword, setShowPassword] = useState(false)
<Input.Root size="md" required>
<Input.Label>
Password
<Input.RequiredIndicator />
</Input.Label>
<Input.Field>
<Input.LeftSlot>
<Lock />
</Input.LeftSlot>
<Input.NativeInput
type={showPassword ? 'text' : 'password'}
placeholder="Enter password..."
/>
<Input.RightSlot>
<button onClick={() => setShowPassword(!showPassword)}>
{showPassword ? <EyeClosed /> : <Eye />}
</button>
</Input.RightSlot>
</Input.Field>
<Input.Hint>Must be at least 8 characters</Input.Hint>
</Input.Root>Controlled Input
Control the input value externally with validation feedback.
Minimum 3 characters required
(empty)const [value, setValue] = useState('')
const isValid = value.length >= 3
<TextInput
label="Username"
placeholder="Enter username..."
value={value}
onChange={(e) => setValue(e.target.value)}
error={value.length > 0 && !isValid ? 'Username must be at least 3 characters' : undefined}
hint={isValid ? 'Username is valid!' : 'Minimum 3 characters required'}
required
/>All States Overview
Small (36px)
Default
This is a hint text to help users.
Disabled
This is a hint text to help users.
Error
This is a hint text to help users.
Medium (40px)
Default
This is a hint text to help users.
Disabled
This is a hint text to help users.
Error
This is a hint text to help users.
Large (44px)
Default
This is a hint text to help users.
Disabled
This is a hint text to help users.
Error
This is a hint text to help users.
Accessibility
- Labels are properly associated with inputs via
htmlFor/id aria-describedbyconnects hint/error text to the inputaria-invalidis set when in error statearia-requiredis set for required fields- Focus states are clearly visible
- Full keyboard navigation support
API Reference
TextInput Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | - | Label text above the input |
| hint | string | - | Helper text below the input |
| error | boolean | string | false | Error state or error message |
| size | 'sm' | 'md' | 'lg' | 'md' | Input size variant |
| leftIcon | ReactNode | - | Icon on the left side |
| rightIcon | ReactNode | - | Icon on the right side |
| kbd | string | - | Keyboard shortcut badge |
| showOptionalBadge | boolean | false | Show "(Optional)" badge |
| showInfoIcon | boolean | false | Show info icon in label |
| tooltip | string | - | Tooltip content for the info icon (auto-shows icon) |
| disabled | boolean | false | Disable the input |
| required | boolean | false | Mark as required |
All standard HTML input attributes are also supported.
PasswordInput Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | - | Label text above the input |
| hint | string | - | Helper text below the input |
| error | boolean | string | false | Error state or error message |
| size | 'sm' | 'md' | 'lg' | 'md' | Input size variant |
| showVisibilityToggle | boolean | true | Show/hide password toggle button |
| defaultVisible | boolean | false | Initial password visibility state |
| onVisibilityChange | (visible: boolean) => void | - | Callback when visibility changes |
| showLeftIcon | boolean | true | Show lock icon on left |
| showOptionalBadge | boolean | false | Show "(Optional)" badge |
| showInfoIcon | boolean | false | Show info icon in label |
| tooltip | string | - | Tooltip content for the info icon (auto-shows icon) |
| disabled | boolean | false | Disable the input |
| required | boolean | false | Mark as required |
All standard HTML input attributes (except type) are also supported.
Compound Components
| Component | Description |
|---|---|
Input.Root | Container that provides context (size, state, error, required) |
Input.Label | Label element with proper association |
Input.RequiredIndicator | Blue asterisk for required fields |
Input.OptionalBadge | "(Optional)" text badge |
Input.InfoIcon | Info icon in label row |
Input.Field | Input field wrapper with border and states |
Input.LeftSlot | Left icon/content container |
Input.RightSlot | Right icon/content container |
Input.NativeInput | The actual <input> element |
Input.Kbd | Keyboard shortcut badge |
Input.Hint | Hint/error text below the field |