Input
A single-line text field, built on the headless Field primitive. Monochrome by design — it shares the Button size steps but none of its colour sets.
src/components/ui/input.tsxAbout
From the component's own source, where it was written.
Built on the headless Field primitive, so clicking the padding or an icon focuses the control rather than doing nothing.
Deliberately monochrome: an input is a surface you type on, not an accent, so it uses only the theme's own background, border and foreground tokens and has no color or tint. It also takes no focus ring and no border change — the caret is the focus indicator. error is the single exception: the one state that earns a colour.
Install
npx astralyx-ui add input
Usage
import { Input } from '@/components/ui/input'
import { Search } from 'lucide-react'
<Input placeholder="Search components" icon={<Search />} />Composer
Change the props and the source below follows.
<Input
placeholder="Search components"
icon={<Search />}
clearable
/>Examples
Variants
<Input placeholder="Default" /> <Input variant="secondary" placeholder="Secondary" /> <Input variant="ghost" placeholder="Ghost" />
Sizes
<Input size="xs" placeholder="Extra small" /> <Input size="sm" placeholder="Small" /> <Input size="default" placeholder="Default" /> <Input size="lg" placeholder="Large" /> <Input size="xl" placeholder="Extra large" />
Icon position
<Input icon={<Search />} placeholder="Leading icon" />
<Input icon={<Mail />} iconPosition="end" placeholder="Trailing icon" />
<Input placeholder="No icon" />Clearable
<Input clearable defaultValue="Clear me" />
<Input clearable icon={<Search />} defaultValue="With a leading icon" />
<Input clearable size="lg" defaultValue="Any size" />States
<Input placeholder="Disabled" disabled /> <Input placeholder="Error" error defaultValue="not-an-email" /> <Input placeholder="Read only" readOnly defaultValue="Read only" />
Aligned with a Button
<Input placeholder="Email" icon={<Mail />} />
<Button>Subscribe</Button>API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
Input
Extends Omit<ComponentProps<'input'>, 'size' | 'style'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| error | boolean | false | The only colour the component takes: a red border. Also sets aria-invalid on the field. |
| variant | 'default' | 'secondary' | 'ghost' | 'default' | Bordered, filled, or no chrome until hover. |
| size | 'sm' | 'default' | 'xs' | 'lg' | 'xl' | 'default' | Height, padding, text and corner radius — the same steps a Button uses, so the two align in a row. |
| icon | ReactNode | — | Rendered inside the field. Padding tightens automatically on the icon side. |
| iconPosition | 'start' | 'end' | 'start' | Which side the icon sits on. |
| clearable | boolean | false | Shows a clear button on the trailing side once the field has content. Works controlled or uncontrolled. |
| onClear | () => void | — | Fires after the clear button empties the field, in addition to the usual onChange. |
| clearLabel | string | 'Clear' | Accessible label for the clear button. |
| containerClassName | string | — | Styles the wrapper. className goes to the <input> itself, so both are reachable. |
| style | ComponentProps<'div'>['style'] | — | — |
Functions
| Function | Signature | Description |
|---|---|---|
| inputVariants | (props?: { variant?: 'default' | 'secondary' | 'ghost'; size?: 'sm' | 'default' | 'xs' | 'lg' | 'xl'; error?: boolean }) => string | Built on the headless Field primitive, so clicking the padding or an icon focuses the control rather than doing nothing. |