#11348·openobserve

feat(web): Global Command Palette — Cmd+K / Ctrl+K page & entity search

Author: bjp232004Created Apr 21, 2026Updated Sep 16, 2026
LabelsIn Progress✏️ Feature

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

already contain meta.title.

Add the following optional fields:

typescript
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:

  • viewDashboard
  • addPanel
  • traceDetails

2. Static Page Index — useCommandPalette.ts

Create a new composable:

web/src/composables/useCommandPalette.ts

Responsibilities

  • 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 pts
    • title.includes(query)1 pt
    • keywords.includes(query)0.5 pt
  • Sort by score (descending)

  • Remove zero-score results


3. Recents Tracking

Add router hook in:

router/index.ts
typescript
router.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.vue

Structure

GlobalCommandPalette.vue
  q-dialog (seamless, position="top")
    ├── Search input
    └── Result list
          └── Section Header
                └── ResultItem

UI Behavior

  • Built using Quasar q-dialog

  • Appears 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
xml
<GlobalCommandPalette />

Register global shortcut:

typescript
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.ts

Stores:

isOpen state

Allows 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 alerts

UI

  • 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-test attributes (global-command-palette-*)

  • No px units or hardcoded colors — use var(--o2-*) tokens

  • Works in both light and dark themes

  • Unit tests cover:

    • open/close behavior
    • filtering
    • keyboard navigation
    • recents persistence
    • empty state

Alternatives considered

NA