Search view

mandatory

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).

Spec β€” Search view

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

Search bar vs search view

Surface What it is When
*earch bar* Inline text field with πŸ” leading icon, sometimes mic Persistent search affordance in toolbar / hero
*earch view* Full-screen overlay with results / suggestions Active 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)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • *ontainer bg* surface (full-screen, no transparency)
  • *eader* 64 px tall, contains back arrow / dismiss / mic /

    clear-text actions

  • *ield* body-large text, hint text body-large text-muted
  • *ection subheaders* label-large, text-muted, 16 px padding
  • *ecent / suggestion rows* list rows per lists.kmd (single-line

    default; leading icon 24 px)

R1 β€” Header layout

Slot Element
Leading Back arrow (← or arrow-down depending on platform) β€” dismisses search view
Field Editable text input; expands across remaining width
Trailing 1 Clear-text Γ— (visible when field has text)
Trailing 2 Mic / voice search button (if voice supported)
Trailing 3 Avatar / settings icon (optional)

R2 β€” Empty state (no text typed)

Shows:

  1. *ecent searches*β€” last 5-10, with clock icon
  2. *uggestions*β€” contextual (recent items, popular actions)
  3. *ilter 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: peruser, perdevice (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 β€” pushtotalk 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

Key Action
Arrow Up / Down Move focus through results / recents
Enter Submit current text as full search OR select focused result
Esc Dismiss search view, return to underlying screen
Tab Move focus across filter chips
Backspace (in field) Delete char; if field empty, focus stays in field

R9 β€” Animation

  • *pen* search bar transforms into search view (motion-medium,

    ~300 ms emphasized) β€” bar grows to fill screen

  • *lose* reverse animation; search view shrinks back to bar
  • *esult update* crossfade old β†’ new (motionfast, ~150 ms)
  • *ilter chip toggle* results re-shuffle with fade
  • Reduced motion: instant open / close; no shrink-grow

R10 β€” Persistence

Field state on dismiss Behavior
Empty field, no submitted search Don't add to recents
Submitted search Add to recents (most recent first)
Typed text but didn't submit Discard (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

Density Header height Result row height
Compact 56 px 48 px
Default 64 px 56 px
Comfortable 72 px 64 px

R14 β€” Per-preset variation

Preset Header Result row
material3 Surface bg, no border below Tonal hover
material2 Solid bg, 4 dp shadow Filled hover
ios_cupertino Cancel button (text) instead of back arrow Inset list rows
gnome Adwaita header bar, integrated mic Boxed list
windows_11 Mica backdrop, Fluent fonts Highlight bar on hover
brutalist Sharp solid header, thick border-bottom Sharp result rows
terminal_classic Single line /search>, results below as text Numbered 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 subpage (NOT fullscreen / 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.kmd β€” surface for container
  • voice/wake-word.kmd β€” voice trigger contract
  • interaction/states.kmd β€” focused result tint
  • foundations/elements.kmd β€” Container + Control families

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/search-view.kmd