Skip to content

STORY-F-018: Command Bar (Cmd+K) overlay on authenticated pages

Epic: UX Priority: Must Have Story Points: 2 Status: Not Started Assigned To: Unassigned Created: 2026-04-17 Sprint: 4


User Story

As an authenticated user (power user in particular), I want a Cmd+K / Ctrl+K command bar overlay accessible on every authenticated page, supporting natural-language navigation, queries, and quick actions, so that the Phase 0 deliverable ("Cmd+K navigates") is complete and Part 13 three-paths-to-every-action is structurally real (Agent / Notification / Navigation).


Description

Background

Architecture §Architectural Invariants + Part 13 commit to three paths: Agent (Cmd+K), Notification, Navigation. B09 brainstorm says "Cmd+K on every screen." FE-15 guardrail makes it advisory; Phase 0 makes it real.

This story lands the overlay component, basic routing intents (navigate to a page), and deep-link query routing to the Agent Chat (F-017). Advanced conversational-form pre-fill (PRD E8.5) is out of scope — that lands with Scout+Verify when real forms exist.

Scope

In scope:

  • FinnestWeb.CommandBar LiveView component (mounted globally via FinnestWeb.Layouts.app.html.heex):
  • Keyboard shortcut: Cmd+K (macOS) / Ctrl+K (Windows/Linux) opens overlay
  • Esc closes overlay
  • Up/Down arrow keys navigate suggestions; Enter selects
  • Input supports free text; debounce 150 ms before triggering suggestion lookup
  • Intent routerFinnestWeb.CommandBar.Router:
  • Pattern match FIRST (Tier 1 per Agent Orchestrator pattern):
    • "go to ___", "navigate ___", "open ___" → navigation intent; matches against a page registry (home, agent chat, admin, etc.)
    • "show ___" for data not yet built → route to agent chat (F-017)
    • User name search: matches ^\S+ \S+$ → search users in org (F-007), show results
    • Role-scoped: admin/director see admin pages in results; workers see only their own
  • Fallback: when no pattern matches → route to agent chat with query pre-populated (seamless handoff to Tier 2)
  • Page registry — list of navigable pages with keywords: %{url: "/", title: "Home", keywords: ["home", "dashboard"]}, %{url: "/users", title: "Users", keywords: ["users", "people", "team"]}, etc. Minimal Phase 0 registry; expands as each domain's routes land.
  • Recent actions cache — last 10 successful selections per user, shown as initial suggestions when overlay opens empty
  • Results rendering — DaisyUI list with icon + title + optional subtitle + keyboard hint
  • Accessibility (FE-05, FE-06, FE-14):
  • 44px touch targets
  • ARIA roles: combobox, listbox, option; live region announcing result count
  • Focus trap inside overlay
  • Screen-reader announces "Command Bar opened" / "Command Bar closed"
  • Security: command bar only shows results the user has permission to see (role scoped); search results checked against authorisation (E1.4 + auth plugs)
  • Integration test: Cmd+K from any authenticated route opens overlay; "go to users" navigates to /users; "what does Finnest do" routes to agent chat with query pre-filled

Out of scope:

  • Agent pre-fill conversational forms (PRD E8.5 — Scout+Verify sprints)
  • Complex fuzzy search (substring match is sufficient Phase 0)
  • Recent-search sync across devices (session-local only)
  • Voice input

Technical Notes

  • Keyboard shortcut binding: Alpine.js @keydown.window.cmd.k.prevent="open = true" (Alpine is the approved local-state tool per FE-11; no global state needed)
  • Command bar render is Alpine for open/close state + LiveView for result fetching (hybrid pattern common in LV apps)
  • Debounce: LiveView phx-debounce="150" on input
  • Page registry could be a compile-time constant assembled by each domain at their discretion (call-out: later sprints extend it). For Phase 0, hardcode in FinnestWeb.CommandBar.PageRegistry.
  • Overlay z-index: ensure it stacks above everything except modals
  • Cmd+K doesn't conflict with browser default on macOS Safari — test explicitly
  • Module namespace: the command bar is a web-layer concern — modules live under FinnestWeb.CommandBar.* (flat FinnestWeb, not Finnest.Web.* or Finnest.CommandBar.*). Boundary library constraint per F-003 precedent.

Dependencies

  • Blocked by: STORY-F-004 (web + DaisyUI), STORY-F-006 (authenticated routes), STORY-F-017 (agent chat for fallback handoff)

Acceptance Criteria

  • Cmd+K (macOS) / Ctrl+K (others) opens overlay from any authenticated page
  • Esc closes overlay; focus returns to previously-focused element
  • Empty-input state shows last 10 recent actions (if any) OR prompt text
  • Typing "go to home" + Enter navigates to /
  • Typing "open users" + Enter navigates to /users
  • Typing a user's name shows matching users (scoped to current user's permissions)
  • Typing free text (non-pattern) + Enter → navigates to agent chat with query pre-filled and auto-submitted
  • Arrow keys navigate results; Enter selects highlighted; escape cancels
  • Accessibility: keyboard-only operable; screen reader announces actions; focus trap works
  • Touch targets ≥44px
  • Contrast ratios meet WCAG AA
  • Command bar responds in <50 ms to input change (debounced)
  • Role-scoped: worker role doesn't see admin pages in results
  • Recent actions persist across LiveView reconnect (stored in session)
  • mix format, credo --strict, dialyzer, mix boundary all green

Testing Requirements

  • LiveView test: keyboard shortcut → overlay open; Esc → overlay close
  • LiveView test: natural-language → correct navigation
  • LiveView test: fallback to agent chat on no match
  • Role-scoping test: worker user searches "admin" → no admin pages shown
  • Accessibility: axe-core run on page with overlay open; live-region + roles asserted
  • E2E (Playwright): open → type → navigate on 3 critical flows

References