improvement(search): redesign Cmd-K palette with curated empty state and drill-down browse#5194
improvement(search): redesign Cmd-K palette with curated empty state and drill-down browse#5194waleedlatif1 wants to merge 8 commits into
Conversation
…and drill-down browse - Stop dumping the full ~1,500-item catalog (blocks, tools, triggers, 1,000+ tool operations, docs) into the palette on open; surface them only once the user types, mirroring the existing integrations group - Add a curated empty state: frecency-ranked Recents (new persisted store) and a Browse section that drills into block/trigger/integration categories - Scope drill-down shown as a removable pill in the search bar; Backspace on empty input or Escape pops the scope - Cap each result group to keep the DOM bounded on broad queries - Derive browse categories from block category + integrationType
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Browse drill-down adds Input reset is centralized in Reviewed by Cursor Bugbot for commit 2848a0b. Configure here. |
Greptile SummaryThis PR redesigns the Cmd-K command palette to gate the full block/tool catalog behind search, replacing the previous 1,500-row unvirtualized render with a curated empty state featuring frecency-ranked recents and a drill-down browse panel. A new persisted
Confidence Score: 5/5Safe to merge after confirming the docx.cjs bundle change is intentional or reverting it. The search-modal logic is well-structured: catalog gating, frecency scoring, scope drill-down, and Escape/Backspace navigation all behave correctly. The frecency pruning regression was addressed in a prior commit and is now covered by a dedicated test. The only outstanding question is the unrelated docx.cjs bundle appearing in the diff. apps/sim/lib/execution/sandbox/bundles/docx.cjs — verify this bundle change was intentional and not an accidental staging artifact. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant SearchModal
participant RecentsStore
participant SearchStore
User->>SearchModal: Cmd-K (open)
SearchModal->>SearchModal: reset search + scope (prevOpen pattern)
SearchModal->>RecentsStore: read entries (frecency-sorted)
SearchModal->>SearchStore: read categories (blocks, triggers, integrations)
SearchModal-->>User: Show Recents + Browse groups (empty state)
User->>SearchModal: Click Browse category (e.g. AI)
SearchModal->>SearchModal: enterScope(category) → setScope + clearInput
SearchModal-->>User: Show scope pill + scoped tool list
User->>SearchModal: Backspace / Escape on empty input
SearchModal->>SearchModal: exitScope() → setScope(null) + clearInput
SearchModal-->>User: Return to empty state (Recents + Browse)
User->>SearchModal: Type query
SearchModal->>SearchModal: cappedCatalog → filterAndSort (≤50 per group)
SearchModal-->>User: Show scored results (blocks, tools, triggers, ops, docs)
User->>SearchModal: Select a block
SearchModal->>RecentsStore: record(block-type)
SearchModal->>SearchModal: dispatch add-block-from-toolbar + close
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant SearchModal
participant RecentsStore
participant SearchStore
User->>SearchModal: Cmd-K (open)
SearchModal->>SearchModal: reset search + scope (prevOpen pattern)
SearchModal->>RecentsStore: read entries (frecency-sorted)
SearchModal->>SearchStore: read categories (blocks, triggers, integrations)
SearchModal-->>User: Show Recents + Browse groups (empty state)
User->>SearchModal: Click Browse category (e.g. AI)
SearchModal->>SearchModal: enterScope(category) → setScope + clearInput
SearchModal-->>User: Show scope pill + scoped tool list
User->>SearchModal: Backspace / Escape on empty input
SearchModal->>SearchModal: exitScope() → setScope(null) + clearInput
SearchModal-->>User: Return to empty state (Recents + Browse)
User->>SearchModal: Type query
SearchModal->>SearchModal: cappedCatalog → filterAndSort (≤50 per group)
SearchModal-->>User: Show scored results (blocks, tools, triggers, ops, docs)
User->>SearchModal: Select a block
SearchModal->>RecentsStore: record(block-type)
SearchModal->>SearchModal: dispatch add-block-from-toolbar + close
Reviews (2): Last reviewed commit: "fix(search): type category icon map by t..." | Re-trigger Greptile |
- Fix stale input text when entering/exiting a browse scope: the cmdk
Command.Input is uncontrolled, so resetting requires the native value
setter, not just setSearch(''). Extract the existing open-reset logic into
a shared clearInput() and reuse it for open, enter-scope, and exit-scope
- Short-circuit the recents memo when there are no recorded entries
- Use a distinct icon for the Productivity category (was reusing Core Blocks')
- Add unit coverage for the recents store and frecency scoring
…etically - Lead with workflow primitives (Core Blocks, Triggers), then pin AI first (Sim is an AI workspace) and rank remaining integration categories by breadth (most integrations first) so the richest categories surface first - Personal frequency is already covered by Recents, so the static order optimizes for discovery and self-maintains as integrations are added - Reuses the canonical integration taxonomy (INTEGRATION_TYPE_LABELS) shared with the /integrations page rather than inventing a parallel one
…tive Review-loop findings: - Recents were pruned by raw recency but ranked by frecency, so a frequently used older block could be evicted while still ranking high. Prune by the same frecencyScore used for display; add a regression test - Make the integration category icon map exhaustive over IntegrationType so a newly added category is a compile error instead of a silent generic-icon fallback; drive core-block/trigger icons off the category kind - Factor the shared gate-and-cap rule for the catalog search groups into a single cappedCatalog() helper instead of repeating it across five memos
…the palette Workflows/files/chats/tables/KBs were rendered in full at the empty state, so a workspace with thousands of them dumped thousands of rows into the DOM. Factor the catalog cap into a shared filterAndCap() and apply it to all variable-size groups, bounding palette DOM to MAX_RESULTS_PER_GROUP per group regardless of workspace size.
…es them The directory imports resolve to the search-groups and command-items barrels; BrowseGroup, RecentsGroup, RecentRenderItem, and MemoizedCategoryItem were added to the source files but not re-exported, breaking the Turbopack build (tsc resolved them via the source file and missed it).
…cideIcon
The map mixes lucide and emcn icons (Database comes from @/components/emcn/icons,
which is not a LucideIcon). Type it as ComponentType<{ className?: string }> —
the exact type MemoizedCategoryItem's icon prop consumes — which both icon
sources satisfy, keeping the exhaustive IntegrationType key check.
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2848a0b. Configure here.
Summary
What changed
category+integrationType. Selecting one scopes the list to just that category. Typing from the root still does a flat global search.Toolbar block picker (separate component) intentionally left as a follow-up to keep this PR focused.
Type of Change
Testing
store.test.tsupdated + new coverage forintegrationTypecapture and category building (5/5 passing)tscclean (0 errors), biome cleanChecklist