Quire UI
Controls10

Input

Text input with slots, a clear button, a focus shortcut, and fields whose errors never shift the layout.

$USD
.com

Installation

npx shadcn@latest add @quireui/input

Field and Form, used below for labels, errors and validation, are separate items:

npx shadcn@latest add @quireui/field @quireui/form

Usage

<Field>
  <FieldLabel>Company name</FieldLabel>
  <Input placeholder="Acme Inc." />
</Field>

Leading and trailing

leading and trailing take an icon, a unit or a short text. Clicking them focuses the input.

<Input leading={<MagnifyingGlassIcon />} placeholder="Search" />
<Input leading="$" trailing="USD" inputMode="decimal" />

Clearable

clearable shows a clear button while there is text, and Esc clears too. Esc on an empty field still reaches whatever is around it, so a dialog closes as expected. Clearing fires onChange like typing does, so controlled inputs need nothing extra.

<Input value={query} onChange={(e) => setQuery(e.target.value)} clearable />

Shortcut

shortcut focuses and selects the field from anywhere on the page. The key badge shows while the field is empty and not focused.

<Input leading={<MagnifyingGlassIcon />} placeholder="Search" shortcut="/" />

Field

Wrap an input in Field to connect its label, description and error. The error line is reserved by default, so a message appearing never pushes the form down. Validation comes from Base UI: native constraints like required or type="email", or your own validate function.

We send the receipt here.

Put fields inside Form. It validates everything on submit and turns off the browser's own popups, so errors always appear in FieldError with the same wording in every browser.

<Form onFormSubmit={save}>
<Field validationMode="onBlur">
  <FieldLabel>Work email</FieldLabel>
  <Input type="email" required />
  <FieldDescription>We send the receipt here.</FieldDescription>
  <FieldError />
</Field>
</Form>

FieldError shows short messages instead of the browser's long ones, which would wrap and break the reserved line: "Required", "Check the format", "Too short" and so on. Override any of them, and messages from your own validate function show as written.

<FieldError messages={{ typeMismatch: "Enter a work email" }} />

Pass reserve={false} where the extra line would look odd, like a single search field.

Accessibility

The field takes its label and its error message from its Field, so the error is read with the field. The clear button is named "Clear" and is hidden from screen readers while there is nothing to clear.

KeyAction
EscWith clearable and text in the field: clears it. On an empty field Esc passes through, so a surrounding dialog closes.
The shortcut keysFocuses the field and selects its text from anywhere on the page. Shortcuts without a modifier never fire while someone is typing.
TabThe clear button is only in the tab order while there is text to clear.

API reference

Input

Prop

Type

Also takes every prop of Base UI's Input. Style it with [data-slot="input"].

On this page