From 72a2f79701addaf2034418d1a02bbb8144392f90 Mon Sep 17 00:00:00 2001 From: Waleed Date: Wed, 28 Jan 2026 12:39:00 -0800 Subject: [PATCH] improvement(search-modal): add quick navigation items and fix cmdk value uniqueness (#3050) * improvement(search-modal): add quick navigation items and fix cmdk value uniqueness * rerank --- .../components/search-modal/search-modal.tsx | 65 +++++++++++++------ apps/sim/stores/modals/search/store.ts | 2 +- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx index 732b4056e..163eb49f4 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx @@ -2,9 +2,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Command } from 'cmdk' -import { BookOpen, Layout, ScrollText } from 'lucide-react' +import { Database, HelpCircle, Layout, Settings } from 'lucide-react' import { useParams, useRouter } from 'next/navigation' import { createPortal } from 'react-dom' +import { Library } from '@/components/emcn' import { useBrandConfig } from '@/lib/branding/branding' import { cn } from '@/lib/core/utils/cn' import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils' @@ -15,6 +16,7 @@ import type { SearchDocItem, SearchToolOperationItem, } from '@/stores/modals/search/types' +import { useSettingsModalStore } from '@/stores/modals/settings/store' interface SearchModalProps { open: boolean @@ -43,7 +45,8 @@ interface PageItem { id: string name: string icon: React.ComponentType<{ className?: string }> - href: string + href?: string + onClick?: () => void shortcut?: string } @@ -61,6 +64,7 @@ export function SearchModal({ const inputRef = useRef(null) const [search, setSearch] = useState('') const [mounted, setMounted] = useState(false) + const openSettingsModal = useSettingsModalStore((state) => state.openModal) useEffect(() => { setMounted(true) @@ -70,12 +74,16 @@ export function SearchModal({ (state) => state.data ) + const openHelpModal = useCallback(() => { + window.dispatchEvent(new CustomEvent('open-help-modal')) + }, []) + const pages = useMemo( (): PageItem[] => [ { id: 'logs', name: 'Logs', - icon: ScrollText, + icon: Library, href: `/workspace/${workspaceId}/logs`, shortcut: '⌘⇧L', }, @@ -86,13 +94,26 @@ export function SearchModal({ href: `/workspace/${workspaceId}/templates`, }, { - id: 'docs', - name: 'Docs', - icon: BookOpen, - href: brand.documentationUrl || 'https://docs.sim.ai/', + id: 'knowledge-base', + name: 'Knowledge Base', + icon: Database, + href: `/workspace/${workspaceId}/knowledge`, + }, + { + id: 'help', + name: 'Help', + icon: HelpCircle, + onClick: openHelpModal, + }, + { + id: 'settings', + name: 'Settings', + icon: Settings, + onClick: openSettingsModal, + shortcut: '⌘,', }, ], - [workspaceId, brand.documentationUrl] + [workspaceId, openHelpModal, openSettingsModal] ) useEffect(() => { @@ -179,10 +200,14 @@ export function SearchModal({ const handlePageSelect = useCallback( (page: PageItem) => { - if (page.href.startsWith('http')) { - window.open(page.href, '_blank', 'noopener,noreferrer') - } else { - router.push(page.href) + if (page.onClick) { + page.onClick() + } else if (page.href) { + if (page.href.startsWith('http')) { + window.open(page.href, '_blank', 'noopener,noreferrer') + } else { + router.push(page.href) + } } onOpenChange(false) }, @@ -269,7 +294,7 @@ export function SearchModal({ {blocks.map((block) => ( handleBlockSelect(block, 'block')} icon={block.icon} @@ -287,7 +312,7 @@ export function SearchModal({ {tools.map((tool) => ( handleBlockSelect(tool, 'tool')} icon={tool.icon} @@ -305,7 +330,7 @@ export function SearchModal({ {triggers.map((trigger) => ( handleBlockSelect(trigger, 'trigger')} icon={trigger.icon} @@ -323,7 +348,7 @@ export function SearchModal({ {workflows.map((workflow) => ( handleWorkflowSelect(workflow)} className='group flex h-[28px] w-full cursor-pointer items-center gap-[8px] rounded-[6px] px-[10px] text-left text-[15px] aria-selected:bg-[var(--border)] aria-selected:shadow-sm data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50' > @@ -345,7 +370,7 @@ export function SearchModal({ {toolOperations.map((op) => ( handleToolOperationSelect(op)} icon={op.icon} @@ -363,7 +388,7 @@ export function SearchModal({ {workspaces.map((workspace) => ( handleWorkspaceSelect(workspace)} className='group flex h-[28px] w-full cursor-pointer items-center gap-[8px] rounded-[6px] px-[10px] text-left text-[15px] aria-selected:bg-[var(--border)] aria-selected:shadow-sm data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50' > @@ -381,7 +406,7 @@ export function SearchModal({ {docs.map((doc) => ( handleDocSelect(doc)} icon={doc.icon} bgColor='#6B7280' @@ -400,7 +425,7 @@ export function SearchModal({ return ( handlePageSelect(page)} className='group flex h-[28px] w-full cursor-pointer items-center gap-[8px] rounded-[6px] px-[10px] text-left text-[15px] aria-selected:bg-[var(--border)] aria-selected:shadow-sm data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50' > diff --git a/apps/sim/stores/modals/search/store.ts b/apps/sim/stores/modals/search/store.ts index 624d35e42..ac591e7b3 100644 --- a/apps/sim/stores/modals/search/store.ts +++ b/apps/sim/stores/modals/search/store.ts @@ -129,7 +129,7 @@ export const useSearchModalStore = create()( .filter((op) => allowedBlockTypes.has(op.blockType)) .map((op) => ({ id: op.id, - name: `${op.serviceName}: ${op.operationName}`, + name: op.operationName, searchValue: `${op.serviceName} ${op.operationName}`, icon: op.icon, bgColor: op.bgColor,