Skip to content

Search view

components specs/components/search-view.kmd

Full-screen / overlay search experience triggered from a search field — shows suggestions, recent queries, and live results as the user types. Material parity (`/components/search`). Distinguished from the static inline search bar (a text field with leading 🔍 icon).

When this spec applies

Primary triggers

All triggers

Specification body

Spec — Search view

Facet Visual of Koder Design. Material parity: https://m3.material.io/components/search.

Search bar vs search view

SurfaceWhat it isWhen
Search barInline text field with 🔍 leading icon, sometimes micPersistent search affordance in toolbar / hero
Search viewFull-screen overlay with results / suggestionsActive typing / browsing recent queries

User flow: tap the search bar → search view OPENS over current screen → user types / browses suggestions → user picks a result OR dismisses → returns to underlying screen.

Anatomy

┌──────────────────────────────────────────────┐
│  ← 🔍 Type to search...           ⊗    🎤    │   ← header (always visible)
│ ──────────────────────────────────────────── │
│  Recent                                       │
│  🕐  swift adoption metrics                   │   ← list of recent queries
│  🕐  release planning Q3                      │
│  🕐  customer feedback summary                │
│ ──────────────────────────────────────────── │
│  Suggestions                                  │
│  💡  switch to dark mode (Settings)           │   ← contextual suggestions
│  💡  team standup notes (Documents)           │
│ ──────────────────────────────────────────── │
│  [Files] [Messages] [People] [Settings]       │   ← filter chips (optional)
└──────────────────────────────────────────────┘
  • Container bg: surface (full-screen, no transparency)
  • Header: 64 px tall, contains back arrow / dismiss / mic / clear-text actions
  • Field: body-large text, hint text body-large text-muted
  • Section subheaders: label-large, text-muted, 16 px padding
  • Recent / suggestion rows: list rows per lists.kmd (single-line default; leading icon 24 px)

R1 — Header layout

SlotElement
LeadingBack arrow (← or arrow-down depending on platform) — dismisses search view
FieldEditable text input; expands across remaining width
Trailing 1Clear-text × (visible when field has text)
Trailing 2Mic / voice search button (if voice supported)
Trailing 3Avatar / settings icon (optional)

R2 — Empty state (no text typed)

Shows:

  1. Recent searches — last 5-10, with clock icon
  2. Suggestions — contextual (recent items, popular actions)
  3. Filter chips — scope of search (Files / Messages / People)

If no recent + no suggestions: show illustration + "Start typing to search" hint text.

R3 — Typing state (autocomplete)

As user types:

  • Live results filter in (motion-fast)
  • Sections rearrange: matching recent first, then suggestions, then results
  • Highlight matched substring in results (bold or underline)
  • Debounce: 150-250 ms before triggering remote search

For local-only data (settings, recent files), no debounce — filter instantly.

R4 — Results state (after submit OR sufficient text)

Replaces empty / autocomplete state with grouped results:

   3 results in Files
   📄  swift-adoption-metrics.csv
   📄  swift-q3-plan.md
   📄  swift-velocity.xlsx

   1 result in People
   👤  Swift Tanaka

   No results in Messages
  • Group results by source type
  • Show count per group
  • "No results" entry for empty sources (helpful — user knows search ran)
  • Up to ~20 results visible; "Show more in [source]" link at end of each group

R5 — Filter chips

Optional filter row above results:

  • Filter chips per source type (Files / Messages / People / Settings)
  • Multi-select: each chip narrows scope
  • Use chips.kmd filter variant

When chips are selected, results limit to selected sources.

R6 — Recent management

  • Tap × on a recent row → remove from list + persist removal
  • "Clear all" link at end of recent section
  • Recent search persistence: per-user, per-device (not synced cross-device unless documented)

Privacy: don't include sensitive queries in recents (e.g., DM content); only top-level search strings.

Voice / mic button in header:

  • Tap → mic permission prompt (first time)
  • Granted: opens voice listening overlay (voice/wake-word.kmd § Talk Mode analog UX — push-to-talk variant)
  • Recognized text inserts into field; user can edit or submit
  • Disabled when voice backend not available (see voice/wake-word.kmd § R5 backend availability)

R8 — Keyboard navigation

KeyAction
Arrow Up / DownMove focus through results / recents
EnterSubmit current text as full search OR select focused result
EscDismiss search view, return to underlying screen
TabMove focus across filter chips
Backspace (in field)Delete char; if field empty, focus stays in field

R9 — Animation

  • Open: search bar transforms into search view (motion-medium, ~300 ms emphasized) — bar grows to fill screen
  • Close: reverse animation; search view shrinks back to bar
  • Result update: cross-fade old → new (motion-fast, ~150 ms)
  • Filter chip toggle: results re-shuffle with fade
  • Reduced motion: instant open / close; no shrink-grow

R10 — Persistence

Field state on dismissBehavior
Empty field, no submitted searchDon't add to recents
Submitted searchAdd to recents (most recent first)
Typed text but didn't submitDiscard (don't add)

Recent list deduped by exact-match string.

R11 — Mobile-specific

  • Soft keyboard opens automatically when search view opens
  • Voice button always visible (if mic supported on device)
  • Results list scrolls under keyboard area; insets respect keyboard height

R12 — Accessibility

  • Container: role="dialog" + aria-modal="true" + aria-label="Search"
  • Field: role="searchbox" + aria-label
  • Results: role="listbox" + each result role="option" + aria-selected on focused
  • Recent items: same listbox / option semantics with aria-label indicating "recent"
  • Voice button: aria-label="Voice search"
  • Live region: announces "N results" when results update
  • Screen reader announces transition to search view on open

R13 — Density

DensityHeader heightResult row height
Compact56 px48 px
Default64 px56 px
Comfortable72 px64 px

R14 — Per-preset variation

PresetHeaderResult row
material3Surface bg, no border belowTonal hover
material2Solid bg, 4 dp shadowFilled hover
ios_cupertinoCancel button (text) instead of back arrowInset list rows
gnomeAdwaita header bar, integrated micBoxed list
windows_11Mica backdrop, Fluent fontsHighlight bar on hover
brutalistSharp solid header, thick border-bottomSharp result rows
terminal_classicSingle line /search>, results below as textNumbered list 1) ...

R15 — Forbidden patterns

  • ❌ Search view that doesn't focus the field on open
  • ❌ Search view without back / dismiss affordance
  • ❌ Results that mix sources without grouping (loses scannability)
  • ❌ Submitting on every keystroke for remote search (over-fetches)
  • ❌ Showing "0 results" without telling user what they searched for
  • ❌ Hiding recents entirely when user starts typing (recents that match should still appear)
  • ❌ Saving sensitive recent queries (DM content, credentials, PII)
  • ❌ Search view as a sub-page (NOT full-screen / overlay) — defeats the immersive purpose
  • ❌ Static search bar that pretends to be a search view (no suggestions / recents) — pick one pattern, don't mix
  • components/text-fields.kmd — base field anatomy
  • components/chips.kmd — filter chip variant
  • components/lists.kmd — result row patterns
  • themes/elevation.kmd — search view sits at base surface (overlay, not elevated)
  • themes/color-roles.kmdsurface for container
  • voice/wake-word.kmd — voice trigger contract
  • interaction/states.kmd — focused result tint
  • foundations/elements.kmd — Container + Control families

References