Skip to content

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 ·

Input states

Installation

bunx --bun shadcn@latest add @dga/input

Installs Field too.

Usage

page.tsx
tsx
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.

Sizes

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.

Fills

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".

Prefix and suffix

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.

LTR (English)
RTL (Arabic)

Accessibility

KeyAction
TabMoves focus to the field.
Shift + TabMoves 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-invalid and 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 own aria-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.

Input props
PropTypeDefault
string

Input 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
string

Class names for the native `<input>`. `className` styles the box around it.

No default
string | number

The default value of the input. Use when uncontrolled.

No default
boolean

Disables the field.

No default
(value: string, details) => void

Callback fired when the `value` changes. Use when controlled.

No default
string

Hint shown while empty.

No default
boolean

The text can be read and copied but not changed.

No default
boolean

The form cannot be submitted while the field is empty.

No default
string | number

The 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).
ChangeReason
--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 focusA 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.

View all 6 deviations for this component

Contrast

270 pairs checked · all pass WCAG 2.1 AAShow 45 states
Variant / stateLightDark
filled text18.09:1 AAA15.87:1 AAA
hovered text18.09:1 AAA15.87:1 AAA
focused text10.17:1 AAA12.04:1 AAA
pressed text9.24:1 AAA9.64:1 AAA
pressed placeholder6.69:1 AA5.06:1 AA
pressed prefix and suffix text9.24:1 AAA9.64:1 AAA
underline, focused and pressed18.74:1 3:116.80:1 3:1
placeholder4.77:1 AA6.32:1 AA
prefix and suffix text10.17:1 AAA12.04:1 AAA
icon4.77:1 3:19.38:1 3:1
border, default4.57:1 3:13.80:1 3:1
border, hovered9.73:1 3:112.04:1 3:1
border, focused and pressed17.93:1 3:116.80:1 3:1
underline, error4.62:1 3:14.65:1 3:1
border, error4.62:1 3:14.65:1 3:1
filled text (lighter)17.64:1 AAA14.42:1 AAA
hovered text (lighter)17.64:1 AAA14.42:1 AAA
focused text (lighter)10.17:1 AAA12.04:1 AAA
pressed text (lighter)9.24:1 AAA9.64:1 AAA
pressed placeholder (lighter)6.69:1 AA5.06:1 AA
pressed prefix and suffix text (lighter)9.24:1 AAA9.64:1 AAA
underline, focused and pressed (lighter)18.28:1 3:115.27:1 3:1
placeholder (lighter)4.65:1 AA5.75:1 AA
prefix and suffix text (lighter)9.92:1 AAA10.95:1 AAA
icon (lighter)4.65:1 3:18.52:1 3:1
border, hovered (lighter)9.73:1 3:112.04:1 3:1
border, focused and pressed (lighter)17.93:1 3:116.80:1 3:1
underline, error (lighter)4.62:1 3:14.65:1 3:1
border, error (lighter)4.62:1 3:14.65:1 3:1
filled text (darker)16.44:1 AAA17.04:1 AAA
hovered text (darker)16.44:1 AAA17.04:1 AAA
focused text (darker)10.17:1 AAA12.04:1 AAA
pressed text (darker)9.24:1 AAA9.64:1 AAA
pressed placeholder (darker)6.69:1 AA5.06:1 AA
pressed prefix and suffix text (darker)9.24:1 AAA9.64:1 AAA
underline, focused and pressed (darker)17.03:1 3:118.03:1 3:1
placeholder (darker)6.69:1 AA6.79:1 AA
prefix and suffix text (darker)9.24:1 AAA12.93:1 AAA
icon (darker)4.34:1 3:110.07:1 3:1
border, hovered (darker)9.73:1 3:112.04:1 3:1
border, focused and pressed (darker)17.93:1 3:116.80:1 3:1
underline, error (darker)4.62:1 3:14.65:1 3:1
border, error (darker)4.62:1 3:14.65:1 3:1
border, hover and focus (lighter and darker)4.57:1 3:13.80:1 3:1
read-only text18.09:1 AAA15.87:1 AAA

Text needs 4.5:1, icons and focus rings 3:1. Disabled states are exempt. Full contrast report