Search input
Usage
Use a search input to find vehicles, work orders or parts by free text. Use filters (selects, checkboxes) when people narrow a list by known attributes, and a combobox when they must pick exactly one item from a long list.
- Wrap it in
<search>so it is a landmark; keep a label (visible, or visually hidden when a page heading already says what is searched). - Placeholder shows what can be searched ("Plate, VIN or depot"), never the label.
- Show the / shortcut only for the main search on a page.
- Searching takes longer than about a second? Show the spinner and announce "Searching…".
Anatomy
- Landmark —
<search class="search">with aform - Field —
.input.input--affixed.search__box(from text field) - Search icon (decorative) —
.search__icon - Input —
input[type=search].search__control - Spinner / shortcut hint —
.search__spinner,kbd.search__kbd - Clear button —
button.search__clear[aria-label="Clear search"] - Status —
.search__status[role=status](visually hidden)
Examples
Hover and focus-visible are frozen with .is-hover and .is-focus-visible, which share their rules with the real pseudo-classes.
Search input
Press / anywhere on the page to jump here.
<search class="search" data-shortcut="/">
<form class="search__form" action="/vehicles" method="get">
<label class="label" for="q">Search vehicles</label>
<div class="input input--affixed search__box"> <!-- aria-busy="true" while loading -->
<svg class="search__icon" aria-hidden="true"><use href="#icon-search"></use></svg>
<input class="input__control search__control" id="q" name="q" type="search" aria-keyshortcuts="/">
<span class="search__spinner" aria-hidden="true"></span>
<kbd class="search__kbd" aria-hidden="true">/</kbd>
<button type="button" class="search__clear" aria-label="Clear search" hidden>…</button>
</div>
<p class="search__status sr-only" role="status"></p> <!-- "Searching…", "12 vehicles found" -->
</form>
</search>
API
| Hook | Values | Purpose |
|---|---|---|
.search | block class on <search> | Landmark wrapper; data-enhanced once JS runs |
data-shortcut="/" | attribute | Global key that focuses the field (ignored while typing elsewhere) |
.search__box[aria-busy="true"] | attribute | Loading: spinner replaces the shortcut hint |
.search__clear | part | Shown while filled; clears and returns focus |
.search__status | part (role=status) | Polite loading/result announcements — the app writes the text |
.input--sm | --lg | modifier on the box | Sizes from text field |
.is-hover | .is-focus-visible | docs-only class | Freezes the clear button |
Do and don't
Accessibility
| Key | Behavior |
|---|---|
| / | Focuses the search field (when shortcut enabled and not typing elsewhere) |
| Enter | Submits the search |
| Esc | Clears the field (native for type=search) |
| Tab | Input, then Clear search (when shown) |
- Landmark:
<search>exposes a search landmark so screen-reader users can jump straight to it. - The input role is
searchbox; the shortcut is exposed witharia-keyshortcuts="/", and the visiblekbdhint is hidden from assistive tech. - Clear search is a labelled icon button; after clearing, focus returns to the input.
- Loading and result counts are announced through the polite
role=statusparagraph, not by moving focus.
Tokens
| Custom property | Purpose |
|---|---|
--input-*, --size-control-* | Field border, height (from text field) |
--color-text-muted | Icon, clear button |
--color-action-ghost-bg-hover | Clear button hover |
--color-bg-subtle, --color-border-default, --font-family-mono | Shortcut hint |
--color-action-primary-bg, --motion-duration-slower | Spinner |