Overview
Use for
- Forms, filters, search fields, and in-panel editors.
- Embedding icons or buttons using relative containers.
- Inline forms when paired with smaller button variants.
Avoid for
- Multi-line content—use `Textarea` instead.
- Selection lists—use `Select` or `Combobox` (Command) patterns.
- Password visibility toggles without descriptive labels.
States & patterns
Baseline field
Works with `Label` for accessible name/ID pairing. Placeholder text inherits semantic `text-neutral-strong` token.
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export function EmailField() {
return (
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@pixexid.com" />
</div>
)
}Input with leading icon
Add icons using a relative wrapper. Increase left padding to prevent overlap.
import { Input } from "@/components/ui/input"
import { IconSearch } from "@tabler/icons-react"
export function SearchInput() {
return (
<div className="relative">
<IconSearch className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-neutral-strong" />
<Input className="pl-9" placeholder="Search projects" />
</div>
)
}Validation feedback
Use semantic text colors and `aria-invalid` to ensure assistive technologies announce state.
import { useState } from "react"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Button } from "@/components/ui/button"
export function SubscribeForm() {
const [email, setEmail] = useState("")
const isValid = email.includes("@");
return (
<form className="space-y-3">
<Label htmlFor="newsletter">Join the newsletter</Label>
<Input
id="newsletter"
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
aria-invalid={!isValid}
aria-describedby="newsletter-description"
placeholder="you@pixexid.com"
/>
<p id="newsletter-description" className="text-xs text-neutral-strong">
We send product updates once a week.
</p>
<Button type="submit" disabled={!isValid}>
Subscribe
</Button>
</form>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | React.ComponentProps<'input'>['type'] | 'text' | Standard HTML input types including email, password, number, etc. |
className | string | — | Merge-friendly override for spacing or layout while retaining baseline styles. |
...rest | React.ComponentProps<'input'> | — | All native attributes (value, onChange, aria-*, autoComplete, etc.) are forwarded. |
Accessibility
Keyboard
- Tab moves in and out of fields.
- Honor native input keyboard handling (arrows for `type="number"`, etc.).
- Set `autoComplete` and `inputMode` for mobile-friendly keyboards.
Guidelines
- Always pair with a visible `<Label>` or `aria-label`.
- Provide helper/error text in `aria-describedby` for screen readers.
- Avoid placeholder-only labelling; placeholders should hint formatting, not primary labels.