3.6 KiB
Context-Aware Cmd-K Search
Goal
Make the cmd-k command palette context-aware: when the user is on admin pages, search users, groups, and roles instead of operational data (applications, routes, exchanges, agents).
Background
The CommandPalette component from @cameleer/design-system currently searches five categories: application, exchange, attribute, route, agent. All data is assembled in LayoutShell.tsx and passed as a flat SearchResult[] array. The SearchCategory type is a closed union in the DS.
The DS team is already updating CommandPalette to accept an open SearchCategory type (string instead of fixed union) and handle unknown categories gracefully (title-cased tab labels, default icons).
Approach
Route-based data swap in LayoutShell. The component already tracks isAdminPage via useLocation(). When true, it provides admin search data instead of operational search data. No new providers, contexts, or abstractions.
Design
Search Data Swap (LayoutShell.tsx)
When isAdminPage is true:
- Skip operational data assembly — do not build catalog/agent/attribute search items, do not fire the debounced
useSearchExecutionsquery - Fetch admin data — call existing hooks:
useUsers(),useGroups(),useRoles()fromapi/queries/admin/rbac.ts - Build admin search items — map each entity to a
SearchResult:- Users:
{ id: 'user:{userId}', category: 'user', title: displayName, meta: userId, path: '/admin/rbac' } - Groups:
{ id: 'group:{id}', category: 'group', title: name, meta: parentGroupId ?? 'top-level group', path: '/admin/rbac' } - Roles:
{ id: 'role:{id}', category: 'role', title: name, meta: scope, path: '/admin/rbac' }
- Users:
- Swap —
searchData = isAdminPage ? adminSearchData : operationalSearchData
All three admin collections are small (dozens of items at most) — client-side filtering is sufficient. No server-side search endpoint needed.
Navigation on Select
When the user selects an admin search result:
- Navigate to
/admin/rbacwith location state:{ tab: 'users' | 'groups' | 'roles', highlight: itemId } - Tab mapping from category:
'user' → 'users','group' → 'groups','role' → 'roles' RbacPagereads location state, switches to the correct tab, and highlights the matching item- The
highlightstate is consumed once — after reading, clear it so back-navigation doesn't re-trigger
Submit Handler (Enter without selection)
When the user presses Enter without explicitly selecting a result, navigate to the top (first visible) result — same behavior as selecting it. This matches standard command palette UX.
Operational search behavior (unchanged)
When not on admin pages, search data assembly remains exactly as-is: catalog apps/routes, agents, exchanges (server-side), and attributes.
Files Changed
| File | Change |
|---|---|
ui/src/components/LayoutShell.tsx |
Import admin hooks, build admin search data, swap based on isAdminPage, update handlePaletteSelect for admin categories |
ui/src/pages/Admin/RbacPage.tsx |
Read location state { tab, highlight }, switch tab and highlight item on mount |
Dependencies
@cameleer/design-systemupdate:SearchCategoryopened tostring, unknown categories handled gracefully (DS team already working on this)
Out of Scope
- Audit log search via cmd-k (has its own dedicated filter UI)
- App config search via cmd-k (already accessible via operational sidebar)
- Server-side admin search endpoint (not needed for small collections)
- Admin-specific submit behavior beyond navigating to top result