Skip to content

Search

X-02 · Composites · App components

All elements · Search on the Composites page

Last checked 2026-10-22 · Awaiting approval · Accessibility tests

Copies the bun run a11y:approve command for Search.

Guidance

When to use

  • Use it for any screen where users query a collection of objects, filter it and act on the results.
  • Use it when one result set must be viewable as a list, table, gallery, kanban board or two-pane reader without the surrounding controls changing.
  • Use the filter rail when users narrow results by several properties at once.
  • Use saved views when users return to the same query and filters often.

When to consider something else

  • Use the Inbox when every result set is a canned task search and there is no filter rail. See Inbox.
  • Use a DataGrid on its own for a fixed table that needs column picking but no query or view switch. See DataGrid.
  • Use a Kanban board on its own when the screen is only a status board. See Kanban.
  • Use the app bar search in the Shell for a global jump-to query rather than a full results screen. See App shell.

Usability

Do
  • Keep the toolbar, filter rail and footer the same in every data-view; only __results changes.
  • Show the result count in __count and keep active filters visible as removable chips in __active-filters.
  • Give every result a focusable __open control (the row's primary cell or the card title) that opens its object.
  • In two-pane, select with aria-current="true" and show the object in the right pane instead of opening a window.
  • Rely on the __more menu at narrow widths; it lists the saved views and all five layouts so none becomes unreachable.
  • Give every search screen one toolbar in one order: [select all] · query · save-search bookmark · Filters · sort · scope · spacer · export · refresh · auto-refresh · column settings · list width (two-pane only) · layout and More. Leave out what a screen cannot offer; keep the rest in order.
  • Make the bookmark open a window (Save search, or Edit saved search: Delete… · Cancel · Save as new · Update), not a menu; mark it data-selected with the bookmark glyph while a saved search is on screen.
  • Keep the Column settings gear in the toolbar, left of the layout switch, in every layout; disable it, titled "No settings for this layout", where the layout has none.
Don’t
  • Do not make a whole-row click the only way to open a result; keep the __open button.
  • Do not change the filters or toolbar when the user switches views.
  • Do not mix window and pane behavior in one view.
  • Do not show filters only as color or icon; each active filter chip names its property and value.

Accessibility

Keyboard

Search keyboard
Keys Action
Tab Moves from the query field through Filters, saved views, the view switcher and More, then into the filter rail, the results and pagination.
Enter or Space On a result's __open control, opens the object in a window; on a two-pane row, selects it and shows it in the right pane.
Enter or Space On a view button, switches the view; the pressed button reports aria-pressed="true".
Arrow Down / Arrow Up In the More menu, moves between saved views and layouts; Escape closes it and returns focus to the button.
Escape In an opened object window, closes it and returns focus to the result's open control.

Roles and names

  • The toolbar is role="toolbar"; the binding must give it an aria-label naming the search, as the Inbox does.
  • The query input is labeled Search query; the Filters toggle and view buttons use aria-pressed; icon-only view buttons have aria-label and title.
  • The filter rail is an <aside>; the binding must label it, for example aria-label="Filters".
  • Table view headers carry aria-sort on the sorted <th> with a .qf-table__sort button; row checkboxes are labeled Select <name>.
  • Active-filter remove buttons must name what they remove (Remove Type: Invoice), not just Remove.
  • Pagination is <nav class="qf-pagination" aria-label="Pagination"> with aria-current="page" on the current page.
  • The two-pane split is a .qf-search__resizer (a .qf-resizable__handle, role="separator", aria-controls the list, aria-valuenow/min/max in pixels); the app sets --qf-search-list-width and data-list-width on .qf-search__two-pane. The toolbar's Narrower · Wider · Reset group is the single-pointer alternative (2.5.7).

Focus

  • After a view switch, focus stays on the view control; the results region must not take focus.
  • In two-pane, selecting a row keeps focus on the row; users Tab into the detail pane.
  • After a filter change, keep focus on the filter control and update the count in place.

Other requirements

  • The binding must announce result-count changes after a query or filter change through a polite live region (4.1.3).
  • Status chips carry text, so status is not shown by color alone (1.4.1).
  • The toolbar collapses into the More menu by container width; the screen must still reflow at 320 CSS pixels (1.4.10).
  • Icon-only view and chip-remove buttons must meet 24 by 24 CSS pixels (2.5.8).

Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.

Accessibility tests

WCAG 2.2 AA · Passed

Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.

Search test checklist
Area Automated A person checks
General Passed Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme.
Zoom Passed At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping.
Keyboard Passed Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. (5 rows)
Screen reader Passed With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (7 items)

Approving. When the checklist passes on the checked run, record it with bun run a11y:approve -- search --by "Your name" and commit a11y/approvals.json with the rebuilt pages. All test status

Package

Consumers link one stylesheet, css/classic/index.css, which includes every element. The files below are where this element is defined.

Search package
Source css/classic/composites/data.css
css/classic/composites/inbox-detail.css
css/classic/composites/inbox-list.css
css/classic/composites/inbox.css
Specimens also use Avatar · Box · Button · ButtonGroup · Card · Chip · Control · Divider · EmptyState · Field · Icon · Kanban · Menu · ObjectDisplay · Overlay · Pagination · Select · Table · Tabs · Text · Toggle · Toolbar
Sprites sprites/icons.svg
React Not yet available: the React binding has not started.

Latest updates

Search latest updates
Date Version Breaking Description
2026-10-20 0.1 Yes Classic is the only skin: css/modern/ and js/skin.js are removed, so consumers link css/classic/index.css directly (no data-skin-sheet swap) and keep data-skin="classic" on <html> for scripts. The skin switch is gone from the site's app bar, the shell's identity menu and the Office review strip; theme stays. The per-skin composite pages are single pages: composites/shell.html, inbox.html, overlay-system.html and search.html replace the *.classic.html and *.modern.html pairs
2026-10-20 0.1 No Search: one toolbar on every screen, in one order: query · save-search bookmark (bookmark-plus, or bookmark with data-selected while a saved search is on screen; it opens a window) · Filters (the C-01 pressed disclosure, with its badge) · sort · spacer · Column settings (the gear, left of the layout switch, disabled where a layout has none) · list width (Narrower · Wider · Reset, two-pane only) · layout and More (layouts only). The toolbar's saved-view chips, result count and More ▸ Saved views are gone from the composite. The two-pane split is resizable: .qf-search__resizer, a C-28 Resizable handle in a gap widened to --qf-space-6, with --qf-search-list-width and data-list-width on .qf-search__two-pane and data-resizing while dragged; stacked below 44rem the handle goes (composites/search-split.css), classic skin

All release notes