Skip to content

Input

In the app

Search and text entry. The label owns the border, so the focus colour wraps icon, field and trailing hint together.

@varick/ui/components/inputAdded 26 Aug 2026

Usage

import { Input } from "@varick/ui/components/input";

export function Example() {
  return (
    <Input
      icon={<SearchIcon />}
      placeholder="Search runs"
      onChange={(e) => setQuery(e.target.value)}
    />
  );
}

Variants

Sizes

<Input size="sm" placeholder="Small" />
<Input size="md" placeholder="Medium" />

States

<Input defaultValue="order-to-cash" />
<Input invalid defaultValue="not an email" />
<Input disabled placeholder="Disabled" />

API reference

Every component also accepts className and the native props of its root element.

PropTypeDefaultDescription
size'sm' | 'md''md'28px or 32px tall.
iconReactNodeundefinedLeading 14px icon, muted.
trailingReactNodeundefinedRight-aligned slot: a Kbd, a count, a clear button.
invalidbooleanfalseRed border and aria-invalid on the field.
...propsComponentProps<'input'>value, onChange, placeholder, disabled, name and the rest.

Accessibility

  • Give the field a name: a visible Field label, or aria-label for a lone search box.
  • invalid sets aria-invalid="true"; pair it with a Field error so the reason is spoken.

Styles

The CSS as it appears in the app. The live component above is the same values as Tailwind classes.

.input {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  border: 1px solid var(--hairline);
  border-radius: 4px;
  padding: 0 12px;
  background: #FFFFFF;
  transition: border-color 140ms var(--ease-out);
}
.input:focus-within { border-color: var(--accent); }
.input[aria-invalid="true"] { border-color: var(--danger); }
.input input { border: 0; outline: 0; font-size: 12.5px; min-width: 0; flex: 1; }
.input svg { color: var(--fg-mid); flex-shrink: 0; }