Search
A text input that lets users search or filter content, with live suggestions as they type. Use for any search or filter interaction across the product. Don't use a standard Input field for search interactions.
FigmaDescription
Provides a dedicated search input that accepts typed queries and optionally surfaces live suggestions or filtered results as the user types. Submitting the query triggers a search action.
Global navigation bars, data table toolbars, stakeholder directory pages, consultation lists, and any screen where users need to locate or filter records.
Search is a distinct interaction pattern from general form input. A purpose-built component ensures consistent keyboard behaviour, correct ARIA semantics (role='search', role='combobox'), and a recognisable affordance — the magnifying-glass icon — that signals searchability to users at a glance.
Anatomy
| Part | Required? | Notes |
|---|---|---|
| Search container | Required | Wraps the entire control. Carries role='search' (or is nested inside a |
| Search icon | Recommended | Magnifying-glass icon rendered at the leading edge of the input. Provides a visual affordance. Hidden from the accessibility tree with aria-hidden='true' — the input's label conveys purpose. |
| Text input | Required | The editable field. Receives focus, accepts keyboard input, and fires input/change events that drive filtering or suggestion logic. |
| Clear button | Optional | Appears when the field has a value. Allows one-click dismissal of the current query. Must have an accessible label — 'Clear search' — and return focus to the text input after activation. |
| Suggestions dropdown | Optional | A listbox that appears beneath the input when live suggestions are enabled. Each option is a focusable listbox item. Dismissed on Escape or when focus leaves the composite. |
| Label | Required | Visually hidden labels are acceptable for compact nav-bar placements, but a visible label is required on standalone search panels. Always present in the DOM for screen readers. |
Variants
Default
Full-width search input with visible label, search icon, and optional clear button. No suggestions.
Standalone search panels, table toolbar filters, and anywhere screen space allows a labelled field.
Compact
Reduced-height input with visually hidden label, suitable for navigation bars and dense toolbars.
Global nav search, sidebar filters, and narrow column layouts where vertical space is at a premium.
With suggestions
Adds a suggestions dropdown (combobox pattern) that renders matching options as the user types.
Stakeholder directory lookups, consultation search where known records can be surfaced instantly, and anywhere type-ahead reduces cognitive effort.
With filters
Search input paired with one or more filter chips or a filter trigger button to narrow result scope.
Complex list views with multiple filterable dimensions — for example, filtering consultations by status and region simultaneously.
States
| State | Behaviour |
|---|---|
| Default (empty) | Placeholder text is visible. Search icon is shown. Clear button is hidden. Suggestions dropdown is closed. |
| Focus | 3px focus ring using --op-color-interactive-focus appears around the input container. Suggestions dropdown may open if the field already has a value. |
| Active (has value) | Placeholder is replaced by user input. Clear button becomes visible. If suggestions variant, the dropdown opens and filters to matching options. |
| Loading | A spinner replaces or supplements the search icon to indicate an async lookup is in progress. The input remains editable. Announce 'Loading results' to screen readers via a live region. |
| No results | Suggestions dropdown shows a single non-interactive message item — 'No results found' — when the query matches nothing. Does not close the dropdown automatically. |
| Disabled | Input is non-interactive. Visually dimmed using --op-color-text-disabled and --op-color-bg-disabled. aria-disabled='true' is set. Do not use disabled for loading states — use the Loading state instead. |
| Error | Border switches to --op-color-status-error. An error message appears below the input. Rare for search — typically used when a query format is invalid (e.g. special characters not permitted). |
Usage guidelines
When to use
- Users need to locate a specific record from a large dataset — for example, finding a stakeholder by name in the Open Point directory.
- A list or table can be filtered in real time as the user types.
- A consultation landing page requires a prominent entry point to search published engagements.
- Navigation requires a global search that spans multiple record types.
When not to use
- The dataset is small enough to scan visually — use a filter or select instead to avoid unnecessary complexity.
- The interaction is a form field collecting free-text input for submission — use a standard Input component.
- You need a multi-select filter — use Combobox with multi-select enabled.
- The search triggers a full page navigation — ensure the component is wrapped in a
Do / Don't
Do
Always provide a visible or visually hidden label. Never rely on placeholder text alone as the label.
Don't
Do not use placeholder text as a substitute for a label — placeholder disappears on input and is not reliably announced by all screen readers.
Do
Use role='search' on the wrapping landmark so screen reader users can navigate to the search region directly.
Don't
Do not wrap the search input in a generic div without a landmark role — it becomes invisible to assistive technology navigation.
Do
Debounce live-search queries by 200–300ms to avoid firing a network request on every keystroke.
Don't
Do not fire search requests on every keydown — this creates excessive network load and degrades performance on low-bandwidth government networks.
Do
Announce result counts to screen readers using a live region: 'Showing 14 results for stakeholders'.
Don't
Do not update results silently — users relying on screen readers will have no indication that the list has changed.
Do
Return focus to the search input after the user clears the field with the Clear button.
Don't
Do not move focus to an unrelated element after clearing — it disorients keyboard and screen reader users.
Layout & Spacing
Input height (default): 44px minimum — meets touch target requirement Input height (compact): 36px — desktop/nav use only Horizontal padding inside input: --op-space-12 (12px) left and right Search icon size: 20x20px; gap between icon and text: --op-space-8 (8px) Clear button: 20x20px icon, right-aligned, margin-right --op-space-12 (12px) Label margin-bottom: --op-space-4 (4px) Suggestions dropdown: margin-top --op-space-4 (4px) from input bottom edge; border-radius --op-radius-md (8px); max-height 320px with overflow-y scroll Each suggestion item: padding --op-space-8 (8px) --op-space-12 (12px); min-height 44px Error message: margin-top --op-space-4 (4px); font-size --op-text-sm
Tokens
| Part | Token | Value |
|---|---|---|
| Input background | --op-color-bg-primary | White in light mode; dark surface in dark mode. |
| Input border (default) | --op-color-border-default | 1px solid border. |
| Input border (focus) | --op-color-interactive-focus | 3px focus ring, offset 2px. |
| Input text | --op-color-text-primary | Primary text colour for entered query. |
| Placeholder text | --op-color-text-placeholder | Subdued; must still meet 3:1 against input background. |
| Search icon | --op-color-text-secondary | Slightly subdued to avoid competing with input text. |
| Clear button icon | --op-color-text-secondary | Matches search icon; darkens to --op-color-text-primary on hover. |
| Suggestions dropdown background | --op-color-bg-primary | Matches input background for visual continuity. |
| Suggestions dropdown border | --op-color-border-default | 1px solid, same as input border. |
| Suggestion item (hover/focus) | --op-color-bg-secondary | Subtle highlight; do not use interactive green for hover backgrounds. |
| Suggestion item (selected/active) | --op-color-interactive-default | Green-400; white text on top. Used when an item is keyboard-activated. |
| Error border | --op-color-status-error | Replaces default border colour. |
| Error message text | --op-color-status-error | Paired with --op-color-status-error-bg for inline error banners if needed. |
| Disabled input | --op-color-bg-disabled / --op-color-text-disabled | Background and text both dimmed; pointer-events: none. |
Engineering notes
- The search container should be a