feat(web): Global Command Palette — Cmd+K / Ctrl+K page & entity search
Which OpenObserve functionalities are relevant/related to the feature request?
No response
Description
Users navigating a large observability platform frequently need to jump between pages (Logs, Monitors, Alerts, Pipelines, etc.) or find a specific resource (a stream, a dashboard, an alert). Today this requires knowing the sidebar structure and clicking through menus.
A command palette (like the screenshot) gives users instant keyboard-driven navigation: press Cmd+K / Ctrl+K, type a few characters, and jump anywhere in one step.
Proposed solution
Global Command Palette (Cmd+K / Ctrl+K)
Overview
A global command palette triggered by:
- Cmd + K (macOS)
- Ctrl + K (Windows/Linux)
The palette works on any page and allows searching across multiple categories.
| Section | Source | Latency |
|---|---|---|
| Recents | localStorage — last 8 visited routes |
Instant |
| Pages | Static list derived from router | Instant |
| Entities | Debounced API search (streams, dashboards, alerts) | ~200–400ms |
Phase 1 — Pages + Recents (No API Calls)
1. Enrich Route Metadata
All routes in:
web/src/composables/shared/router.tsalready contain meta.title.
Add the following optional fields:
meta: {
title: "Monitors",
icon: "monitor_heart", // Material icon (same as sidebar)
section: "Observability", // Group label in results
keywords: ["alerts", "SLO"],
searchable: true // false for detail/editor pages
}✅ Only routes with searchable: true appear in results.
Exclude detail/editor pages such as:
viewDashboardaddPaneltraceDetails
2. Static Page Index — useCommandPalette.ts
Create a new composable:
web/src/composables/useCommandPalette.tsResponsibilities
- Build searchable page index from router at startup
- Filter pages using substring search
- Track & persist recent pages (
localStorage) - Manage open/close state
- Handle keyboard navigation
- Navigate using
useRouter()
Search Algorithm
Normalize query and candidates to lowercase
Scoring:
title.startsWith(query)→ 2 ptstitle.includes(query)→ 1 ptkeywords.includes(query)→ 0.5 pt
Sort by score (descending)
Remove zero-score results
3. Recents Tracking
Add router hook in:
router/index.tsrouter.afterEach((to) => {
if (to.meta?.searchable) {
pushRecentPage({
name: to.name,
path: to.path,
title: to.meta.title
})
}
})Rules
- Stored in
localStorage - Key:
o2_recent_pages - Maximum: 8 items
- Newest first
- Deduplicated by route name
4. UI Component — GlobalCommandPalette.vue
Create:
web/src/components/GlobalCommandPalette.vueStructure
GlobalCommandPalette.vue
q-dialog (seamless, position="top")
├── Search input
└── Result list
└── Section Header
└── ResultItemUI Behavior
Built using Quasar
q-dialogAppears near top (VS Code / Linear style)
Sections:
- RECENTS
- PAGES
- ENTITIES
Keyboard Controls
| Key | Action |
|---|---|
| ↑ ↓ | Navigate results |
| Enter | Navigate |
| Escape | Close |
Additional Requirements
- Highlight selected item using
var(--o2-primary-background) - Empty state:
No pages found for "..."Test Selectors
data-test="command-palette-input"
data-test="command-palette-result-item"5. Mounting & Shortcut Wiring
Mount once in:
web/src/App.vue<GlobalCommandPalette />Register global shortcut:
window.addEventListener('keydown', (e) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault()
store.dispatch('commandPalette/open')
}
})Create Vuex module:
web/src/stores/commandPalette.tsStores:
isOpen stateAllows programmatic opening later.
Phase 2 — Entity Search (Follow-up)
Add Entities section after Phase 1 release.
Behavior
- Debounced API search (300ms)
- Trigger when query length ≥ 2
APIs
GET /api/{org}/streams?filter=...
GET dashboards
GET alertsUI
Loading spinner while fetching
Show entity type badge:
- Stream
- Dashboard
- Alert
Navigate to entity detail page on selection
Files to Create
| File | Purpose |
|---|---|
web/src/components/GlobalCommandPalette.vue |
Main UI component |
web/src/composables/useCommandPalette.ts |
Search logic & recents |
web/src/stores/commandPalette.ts |
Vuex state |
web/src/components/GlobalCommandPalette.spec.ts |
Unit tests |
Acceptance Criteria
Cmd+K / Ctrl+K opens palette globally
Escape closes palette
Typing filters pages instantly (no API calls)
Last 8 visited pages shown under Recents when query is empty
Selecting result navigates and closes palette
Clicking outside closes palette
All interactive elements include
data-testattributes (global-command-palette-*)No
pxunits or hardcoded colors — usevar(--o2-*)tokensWorks in both light and dark themes
Unit tests cover:
- open/close behavior
- filtering
- keyboard navigation
- recents persistence
- empty state
Alternatives considered
NA
Source: openobserve/openobserve