Text field on a sunken well in three sizes with a volt focus halo, leading icon, joined text, select and button add-ons, a help tooltip, a clear button and a single shake when an error appears.
inputtext fieldformvalidationerrorsearchadd-oninput group
Installation
$npx shadcn@latest add @geturui/input
Usage
usage.tsx
1import { AtSign } from "lucide-react";
2import { Input, InputAddonSelect } from "@/components/ui/input";
3
4export function EmailField({ error }: { error?: string }) {
5 return (
6 <div className="grid gap-4">
7 <Input
8 label="Email"
9 type="email"
10 placeholder="[email protected]"
11 iconLeading={AtSign}
12 tooltip="Only used for sign-in links."
13 hint="We'll never share it."
14 error={error}
15 clearable
16 />
17 <Input label="Custom domain" leadingAddon="https://" placeholder="ui.yourstudio.com" />
18 <Input
19 label="Budget"
20 leadingAddon="$"
21 trailingAddon={<InputAddonSelect aria-label="Currency" options={[{ value: "usd", label: "USD" }, { value: "eur", label: "EUR" }]} />}
22 />
23 </div>
24 );
25}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — | Visible label, linked to the input. |
hint | ReactNode | — | Helper text under the field. |
error | ReactNode | — | Error text. Replaces the hint, turns the border red, adds an alert icon and shakes once when it appears. |
size | "sm" | "md" | "lg" | "md" | 32, 40 or 48px, matching Button. |
icon | ReactNode | — | Leading icon node inside the field. |
iconLeading | ComponentType | ReactNode | — | Leading icon as a component (Mail) or node, sized to the field. |
leadingAddon / trailingAddon | ReactNode | — | Joined segments. A string renders a text add-on ("https://", "$"); pass InputAddonSelect or InputAddonButton for controls. |
tooltip | ReactNode | — | Help text behind a question-mark button on the label row. |
clearable | boolean | false | Show a clear button while the field has a value. onChange fires with an empty value. |
onClear | () => void | — | Called after the clear button empties the field. |
trailing | ReactNode | — | Content inside the field after the input, such as a status icon. |
kbd | string | — | Keyboard shortcut chip at the end of the field. |
labelAside | ReactNode | — | Right side of the label row: Optional, a counter, a link. |
required / disabled | boolean | false | Required adds a volt asterisk; disabled dims the whole well. |
wrapperClassName | string | — | Classes for the outer grid (label, field, hint). |
className | string | — | Classes for the field well. |
inputClassName | string | — | Classes for the <input> itself. |
...props | InputHTMLAttributes<HTMLInputElement> | — | Any input attribute; ref is forwarded to the <input>. |
Accessibility
- Built on Field: the label is a real <label for>, and the hint or error is linked with aria-describedby (merged with yours).
- error sets aria-invalid and the message carries an icon and words, never colour alone; the shake runs once and is skipped with reduced motion.
- The clear and help buttons are labelled ("Clear", "More info"); InputAddonSelect requires an aria-label. The shortcut chip is aria-hidden.
- The focus halo is drawn on the well so it stays visible in both themes.