Input
betaA one-line text field with sizes and an error state.
Preview
size
states
That name is taken. Try another.
types
field
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/input
Use it for
- Short free text: a name, an email address, a search, a number.
- Name it with a visible label. Give the input an id and point the label's htmlFor at it.
- Set the type that fits the value, like email, tel, url, or search, so phones show the right keyboard.
- Show errors with aria-invalid plus a message under the input, linked with aria-describedby.
Avoid it for
- Text that can run past one line, like a comment or a bio. Use a textarea.
- Choosing from a fixed list. Use a select or a radio group.
- Turning a setting on and off. Use a checkbox or a switch.
- Using placeholder as the label. It disappears as soon as someone types.
Props
- size
Height, padding, and text size. Density scales them.
"sm" | "md" | "lg" · default "md"
- disabled
Blocks typing and removes the input from the tab order.
boolean · default false
- aria-invalid
Shows the danger border. Set it when validation fails, and link the message with aria-describedby.
boolean
- onValueChange
Called with the new text on every change. Use it with value for a controlled input.
(value: string, details) => void
- className
Extra classes. Later classes win, so className='rounded-none' replaces the radius.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "md" | Height, padding, and text size. Density scales them. |
| disabled | boolean | false | Blocks typing and removes the input from the tab order. |
| aria-invalid | boolean | - | Shows the danger border. Set it when validation fails, and link the message with aria-describedby. |
| onValueChange | (value: string, details) => void | - | Called with the new text on every change. Use it with value for a controlled input. |
| className | string | - | Extra classes. Later classes win, so className='rounded-none' replaces the radius. |
Accessibility
- Renders a native <input>, so typing, selection, autofill, and form submission work as usual.
- It has no name on its own. Pair it with a <label htmlFor>, or wrap it in a label.
- aria-invalid="true" tells screen readers the value is wrong. Put the reason in text next to the input, not only in the red border.
- The border uses --input, which the theme tests hold to 3:1 against the page and cards.
- The focus ring uses --ring, which the theme tests hold to 3:1 against the page and cards.
- On touch screens the text is 16px, so iOS Safari does not zoom in when the input gets focus.
Examples
With a label
<div className="grid gap-2">
<label htmlFor="email" className="text-sm font-medium">
Email
</label>
<Input id="email" type="email" autoComplete="email" placeholder="you@example.com" />
</div>Error message the input points to
<div className="grid gap-2">
<label htmlFor="handle" className="text-sm font-medium">
Username
</label>
<Input id="handle" defaultValue="admin" aria-invalid aria-describedby="handle-error" />
<p id="handle-error" className="text-sm text-destructive-soft-foreground">
That name is taken. Try another.
</p>
</div>Small, in a toolbar
<Input size="sm" type="search" aria-label="Search projects" placeholder="Search" />