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.CommandBarLiveView component (mounted globally viaFinnestWeb.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 router —
FinnestWeb.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.*(flatFinnestWeb, notFinnest.Web.*orFinnest.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 boundaryall 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¶
../architecture/architecture.md§Architectural Invariants, Part 13 (Three paths)../brainstorms/brainstorm-09-ui-ux-vision.md§Command Bar (Cmd+K)../10-GUARDRAILS.mdFE-05, FE-06, FE-14, FE-15, FE-16