Input
A single-line text field. Two sizes, three fills, prefix and suffix, and every state: hover, focus, filled, read-only, disabled and error.
Version 0.4.1 ·
Installation
bunx --bun shadcn@latest add @dga/inputInstalls Field too.
Usage
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
export function NameField() {
return (
<Field name="name">
<FieldLabel required>Full name</FieldLabel>
<Input required autoComplete="name" />
<FieldDescription>As it appears on your ID card.</FieldDescription>
</Field>
);
}Use Input for short single-line answers: names, IDs, email addresses, phone numbers. Set type and inputMode for the right keyboard, and autoComplete so browsers can fill it in. For numbers you add and subtract use Number Input; for several lines use Textarea.
Anatomy
- Box (
<div>): the border, fill, shadow and the underline. - Start adornment (optional): an icon or a short prefix such as
+966. - Input (
<input>): the text. - End adornment (optional): an icon, suffix or button.
Examples
Sizes
lg is 40px high (default) and md is 32px.
Fills
appearance is default, lighter or darker. As in DGA, lighter and darker have no border at rest; it appears on hover, focus and press. The states below show them all.
Prefix and suffix
startAdornment and endAdornment take an icon or text. They sit on the logical start and end sides. Phone numbers and emails stay left to right with dir="ltr".
RTL
The text, placeholder and adornments start on the right. Typed Arabic aligns right; typed Latin text (an email) aligns with dir="ltr" when you set it.
Accessibility
| Key | Action |
|---|---|
| Tab | Moves focus to the field. |
| Shift + Tab | Moves focus back. |
- A native
<input>: always label it with a Field; a placeholder is not a label. - There is no outline. Hover darkens the border. Pressed (mouse or touch down) shows the pressed fill and the 2px underline at half width, growing from the centre. Focus (mouse or keyboard) shows the pressed border colour, the full-width underline and
shadow-md(no shadow in dark mode). The underline grows from the centre to both sides in LTR and RTL alike, and is at least 3:1 on every fill. - The default border is 3:1 or better against the page, light and dark (WCAG 1.4.11). See Deviations for the two states that are not.
- Errors set
aria-invalidand show an icon with the message. Read-only fields stay focusable; disabled ones do not. - Adornment icons are decorative (
aria-hidden). A suffix button needs its ownaria-label.
API Reference
Input
A single-line text field in a bordered box. Label it with a Field. Use `type="email"`, `"tel"`, `"url"` or `"password"` for the matching keyboard and autofill.
| Prop | Type | Default |
|---|---|---|
stringInput type: `text`, `email`, `tel`, `url`, `password` and so on. | No default | |
| ||
"md" | "lg"Height: `md` 32px, `lg` 40px. | "lg" | |
| ||
"default" | "lighter" | "darker"Fill: `default` (white), `lighter` or `darker`. All three keep a visible border. | "default" | |
| ||
string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>An icon or a short prefix (for example `+966`) before the text, on the start side. | No default | |
| ||
string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>An icon, suffix text or button after the text, on the end side. | No default | |
| ||
stringClass names for the native `<input>`. `className` styles the box around it. | No default | |
| ||
string | numberThe default value of the input. Use when uncontrolled. | No default | |
| ||
booleanDisables the field. | No default | |
| ||
(value: string, details) => voidCallback fired when the `value` changes. Use when controlled. | No default | |
| ||
stringHint shown while empty. | No default | |
| ||
booleanThe text can be read and copied but not changed. | No default | |
| ||
booleanThe form cannot be submitted while the field is empty. | No default | |
| ||
string | numberThe value of the input. Use when controlled. | No default | |
| ||
Also accepts every prop of the Base UI Input (opens in a new tab).
Deviations from DGA
- The default border is neutral-500, not neutral-400 (2.6:1 on white), so the field can be found at rest.
- The placeholder is neutral-500 as in DGA; only on the pressed and darker fills (4.34:1) does it use neutral-600.
- The error border is error-600 (the live DGA CSS), not the Figma error-700.
- A focused read-only field shows the underline, because it is still in the tab order.
- Known gaps, kept as DGA draws them: the read-only border (1.5:1) and the lighter and darker fills at rest (1.0 to 1.1:1).
| Change | Reason |
|---|---|
--field-border-default (light) | DGA draws the default field border in neutral-400 (#9da4ae), which is 2.58:1 on a white field. The default field has a white fill on a white or near-white page, so the border is the only thing that marks its boundary at rest (WCAG 1.4.11, 3:1). Neutral-500 is 4.83:1 on white. Kept only for this reason; hover, focus and press use the DGA colours. Dark mode already passes. |
--field-border-error (light) | Figma binds the error border to red-700 (#b42318); the live DGA CSS (--form-field-border-error) is error-600 (#d92d20), 4.77:1 on white, which still passes 3:1 as a border and 4.5:1 as the required marker. Follows the live DGA colour. |
--field-text-placeholder-tinted (new) | The DGA placeholder (neutral-500, #6c737f) is 4.83:1 on white but 4.34:1 on the filled darker fill and the pressed fill (#f3f4f6), under 4.5:1. Only those two states use this token (neutral-600, 6.2:1); everywhere else the placeholder is the DGA colour. |
Input, Textarea, Select: read-only focus | A read-only field is still in the tab order, and a focused element needs a visible indicator (WCAG 2.4.7). Without an outline, the underline is the indicator. |
Contrast
270 pairs checked · all pass WCAG 2.1 AAShow 45 statesHide
| Variant / state | Light | Dark |
|---|---|---|
| filled text | 18.09:1 AAA | 15.87:1 AAA |
| hovered text | 18.09:1 AAA | 15.87:1 AAA |
| focused text | 10.17:1 AAA | 12.04:1 AAA |
| pressed text | 9.24:1 AAA | 9.64:1 AAA |
| pressed placeholder | 6.69:1 AA | 5.06:1 AA |
| pressed prefix and suffix text | 9.24:1 AAA | 9.64:1 AAA |
| underline, focused and pressed | 18.74:1 3:1 | 16.80:1 3:1 |
| placeholder | 4.77:1 AA | 6.32:1 AA |
| prefix and suffix text | 10.17:1 AAA | 12.04:1 AAA |
| icon | 4.77:1 3:1 | 9.38:1 3:1 |
| border, default | 4.57:1 3:1 | 3.80:1 3:1 |
| border, hovered | 9.73:1 3:1 | 12.04:1 3:1 |
| border, focused and pressed | 17.93:1 3:1 | 16.80:1 3:1 |
| underline, error | 4.62:1 3:1 | 4.65:1 3:1 |
| border, error | 4.62:1 3:1 | 4.65:1 3:1 |
| filled text (lighter) | 17.64:1 AAA | 14.42:1 AAA |
| hovered text (lighter) | 17.64:1 AAA | 14.42:1 AAA |
| focused text (lighter) | 10.17:1 AAA | 12.04:1 AAA |
| pressed text (lighter) | 9.24:1 AAA | 9.64:1 AAA |
| pressed placeholder (lighter) | 6.69:1 AA | 5.06:1 AA |
| pressed prefix and suffix text (lighter) | 9.24:1 AAA | 9.64:1 AAA |
| underline, focused and pressed (lighter) | 18.28:1 3:1 | 15.27:1 3:1 |
| placeholder (lighter) | 4.65:1 AA | 5.75:1 AA |
| prefix and suffix text (lighter) | 9.92:1 AAA | 10.95:1 AAA |
| icon (lighter) | 4.65:1 3:1 | 8.52:1 3:1 |
| border, hovered (lighter) | 9.73:1 3:1 | 12.04:1 3:1 |
| border, focused and pressed (lighter) | 17.93:1 3:1 | 16.80:1 3:1 |
| underline, error (lighter) | 4.62:1 3:1 | 4.65:1 3:1 |
| border, error (lighter) | 4.62:1 3:1 | 4.65:1 3:1 |
| filled text (darker) | 16.44:1 AAA | 17.04:1 AAA |
| hovered text (darker) | 16.44:1 AAA | 17.04:1 AAA |
| focused text (darker) | 10.17:1 AAA | 12.04:1 AAA |
| pressed text (darker) | 9.24:1 AAA | 9.64:1 AAA |
| pressed placeholder (darker) | 6.69:1 AA | 5.06:1 AA |
| pressed prefix and suffix text (darker) | 9.24:1 AAA | 9.64:1 AAA |
| underline, focused and pressed (darker) | 17.03:1 3:1 | 18.03:1 3:1 |
| placeholder (darker) | 6.69:1 AA | 6.79:1 AA |
| prefix and suffix text (darker) | 9.24:1 AAA | 12.93:1 AAA |
| icon (darker) | 4.34:1 3:1 | 10.07:1 3:1 |
| border, hovered (darker) | 9.73:1 3:1 | 12.04:1 3:1 |
| border, focused and pressed (darker) | 17.93:1 3:1 | 16.80:1 3:1 |
| underline, error (darker) | 4.62:1 3:1 | 4.65:1 3:1 |
| border, error (darker) | 4.62:1 3:1 | 4.65:1 3:1 |
| border, hover and focus (lighter and darker) | 4.57:1 3:1 | 3.80:1 3:1 |
| read-only text | 18.09:1 AAA | 15.87:1 AAA |
Text needs 4.5:1, icons and focus rings 3:1. Disabled states are exempt. Full contrast report