Qure UI
Components

Input

A single-line text field.

import { Input } from '@/registry/qure/ui/input'export default function InputDemo() {  return <Input placeholder="ACC-000000" className="max-w-64" />}

Installation

npx shadcn@latest add https://qure-ui.qure.ai/r/input.json

Usage

import { Input } from '@/components/ui/input'
<Label htmlFor="accession">Accession number</Label>
<Input id="accession" placeholder="ACC-000000" />

One line of typed text. For anything longer than a line use a Textarea; for a value chosen from a known set use a Select or a Radio Group, because a free-text field that only accepts nine answers is a spelling test.

Size

import { Input } from '@/registry/qure/ui/input'export default function InputSize() {  return (    <div className="grid w-full max-w-64 gap-3">      <Input size="sm" placeholder="sm · 32px" />      <Input size="md" placeholder="md · 40px" />      <Input size="lg" placeholder="lg · 48px" />    </div>  )}

Heights 32, 40 and 48, matching the Figma field scale. md is the default and pairs with a md Button on the same row. sm is for dense furniture — a filter bar above a worklist, a cell being edited in place — and lg for a single field that is the point of the screen, such as a patient lookup. Do not mix sizes within one form.

With a label and a hint

Six digits, as printed on the requisition.

import { Input } from '@/registry/qure/ui/input'import { Label } from '@/registry/qure/ui/label'export default function InputLabel() {  return (    <div className="grid w-full max-w-xs gap-2">      <Label htmlFor="accession-number">Accession number</Label>      <Input id="accession-number" placeholder="ACC-000000" aria-describedby="accession-hint" />      <p id="accession-hint" className="text-sm text-muted-foreground">        Six digits, as printed on the requisition.      </p>    </div>  )}

The full row: a Label bound by htmlFor, the field, and a hint tied on with aria-describedby. The hint is announced after the label, so it reads as one sentence — keep it to the format or the constraint, not a second label.

With a leading icon

import { SearchIcon } from 'lucide-react'import { Input } from '@/registry/qure/ui/input'export default function InputIcon() {  return (    <div className="relative w-full max-w-72">      <SearchIcon        aria-hidden        className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground"      />      <Input aria-label="Search the worklist" placeholder="Patient, MRN or accession" className="pl-9" />    </div>  )}

The component has no icon slot, and does not need one: position the icon absolutely and pad the field past it. Give the icon aria-hidden and pointer-events-none so it neither speaks nor swallows the click that should focus the field. A search field with a magnifier is the one place aria-label alone is defensible; everything else wants a visible label.

Read-only, invalid and disabled

Accession numbers are six digits.

import { Input } from '@/registry/qure/ui/input'import { Label } from '@/registry/qure/ui/label'export default function InputState() {  return (    <div className="grid w-full max-w-xs gap-4">      <div className="grid gap-2">        <Label htmlFor="mrn-locked">MRN</Label>        <Input id="mrn-locked" readOnly defaultValue="MRN-0043118" />      </div>      <div className="grid gap-2">        <Label htmlFor="acc-invalid">Accession number</Label>        <Input          id="acc-invalid"          data-invalid=""          aria-invalid          aria-describedby="acc-invalid-error"          defaultValue="ACC-48291"        />        <p id="acc-invalid-error" className="text-sm text-[var(--text-urgent-default)]">          Accession numbers are six digits.        </p>      </div>      <div className="grid gap-2">        <Label htmlFor="reported-by">Reported by</Label>        <Input id="reported-by" disabled placeholder="Set when the report is signed" />      </div>    </div>  )}

Three different statements, often confused:

StateMeansFocusable
readOnlyThis value is real but yours to copy, not to changeYes
data-invalidWhat is in here will not be acceptedYes
disabledThis field is not available yet, or not to youNo

An MRN pulled from the RIS is read-only, not disabled — a radiologist copying it into another system should not have to retype it.

Validation

Base UI sets data-invalid when the field fails its Field validation, and the stylesheet recolours the border and focus ring from it. You do not set a state prop; inside a Field you do not set the attribute either. The example above sets it by hand only because it is a static demo, and pairs it with aria-invalid and a described-by message — the colour alone says nothing to anyone who cannot see it.

A placeholder is not a label. It disappears exactly when someone needs it, and screen readers announce it inconsistently. Use a real <label>, and keep the placeholder for format hints like ACC-000000.

size is ours, not the native attribute. The native size counts characters and is shadowed here on purpose — column widths belong to the layout, not to the input.

API Reference

Everything Base UI's Input accepts — including value/onValueChange, defaultValue, readOnly, required and the native input attributes — plus:

Prop

Type

On this page