Skip to content

Commit 209440e

Browse files
committed
improvement(search-modal): add quick navigation items and fix cmdk value uniqueness
1 parent 6814f33 commit 209440e

File tree

2 files changed

+54
-25
lines changed
  • apps/sim

2 files changed

+54
-25
lines changed

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal/search-modal.tsx

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { Command } from 'cmdk'
5-
import { BookOpen, Layout, ScrollText } from 'lucide-react'
5+
import { Database, HelpCircle, Layout, Settings } from 'lucide-react'
66
import { useParams, useRouter } from 'next/navigation'
77
import { createPortal } from 'react-dom'
8+
import { Library } from '@/components/emcn'
89
import { useBrandConfig } from '@/lib/branding/branding'
910
import { cn } from '@/lib/core/utils/cn'
1011
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
@@ -15,6 +16,7 @@ import type {
1516
SearchDocItem,
1617
SearchToolOperationItem,
1718
} from '@/stores/modals/search/types'
19+
import { useSettingsModalStore } from '@/stores/modals/settings/store'
1820

1921
interface SearchModalProps {
2022
open: boolean
@@ -43,7 +45,8 @@ interface PageItem {
4345
id: string
4446
name: string
4547
icon: React.ComponentType<{ className?: string }>
46-
href: string
48+
href?: string
49+
onClick?: () => void
4750
shortcut?: string
4851
}
4952

@@ -61,6 +64,7 @@ export function SearchModal({
6164
const inputRef = useRef<HTMLInputElement>(null)
6265
const [search, setSearch] = useState('')
6366
const [mounted, setMounted] = useState(false)
67+
const openSettingsModal = useSettingsModalStore((state) => state.openModal)
6468

6569
useEffect(() => {
6670
setMounted(true)
@@ -70,12 +74,16 @@ export function SearchModal({
7074
(state) => state.data
7175
)
7276

77+
const openHelpModal = useCallback(() => {
78+
window.dispatchEvent(new CustomEvent('open-help-modal'))
79+
}, [])
80+
7381
const pages = useMemo(
7482
(): PageItem[] => [
7583
{
7684
id: 'logs',
7785
name: 'Logs',
78-
icon: ScrollText,
86+
icon: Library,
7987
href: `/workspace/${workspaceId}/logs`,
8088
shortcut: '⌘⇧L',
8189
},
@@ -86,13 +94,26 @@ export function SearchModal({
8694
href: `/workspace/${workspaceId}/templates`,
8795
},
8896
{
89-
id: 'docs',
90-
name: 'Docs',
91-
icon: BookOpen,
92-
href: brand.documentationUrl || 'https://docs.sim.ai/',
97+
id: 'knowledge-base',
98+
name: 'Knowledge Base',
99+
icon: Database,
100+
href: `/workspace/${workspaceId}/knowledge`,
101+
},
102+
{
103+
id: 'help',
104+
name: 'Help',
105+
icon: HelpCircle,
106+
onClick: openHelpModal,
107+
},
108+
{
109+
id: 'settings',
110+
name: 'Settings',
111+
icon: Settings,
112+
onClick: openSettingsModal,
113+
shortcut: '⌘,',
93114
},
94115
],
95-
[workspaceId, brand.documentationUrl]
116+
[workspaceId, openHelpModal, openSettingsModal]
96117
)
97118

98119
useEffect(() => {
@@ -179,10 +200,14 @@ export function SearchModal({
179200

180201
const handlePageSelect = useCallback(
181202
(page: PageItem) => {
182-
if (page.href.startsWith('http')) {
183-
window.open(page.href, '_blank', 'noopener,noreferrer')
184-
} else {
185-
router.push(page.href)
203+
if (page.onClick) {
204+
page.onClick()
205+
} else if (page.href) {
206+
if (page.href.startsWith('http')) {
207+
window.open(page.href, '_blank', 'noopener,noreferrer')
208+
} else {
209+
router.push(page.href)
210+
}
186211
}
187212
onOpenChange(false)
188213
},
@@ -269,8 +294,8 @@ export function SearchModal({
269294
{blocks.map((block) => (
270295
<CommandItem
271296
key={block.id}
272-
value={block.name}
273-
keywords={[block.description]}
297+
value={`block-${block.name}`}
298+
keywords={[block.name, block.description]}
274299
onSelect={() => handleBlockSelect(block, 'block')}
275300
icon={block.icon}
276301
bgColor={block.bgColor}
@@ -287,8 +312,8 @@ export function SearchModal({
287312
{tools.map((tool) => (
288313
<CommandItem
289314
key={tool.id}
290-
value={tool.name}
291-
keywords={[tool.description]}
315+
value={`tool-${tool.name}`}
316+
keywords={[tool.name, tool.description]}
292317
onSelect={() => handleBlockSelect(tool, 'tool')}
293318
icon={tool.icon}
294319
bgColor={tool.bgColor}
@@ -305,8 +330,8 @@ export function SearchModal({
305330
{triggers.map((trigger) => (
306331
<CommandItem
307332
key={trigger.id}
308-
value={trigger.name}
309-
keywords={[trigger.description]}
333+
value={`trigger-${trigger.name}`}
334+
keywords={[trigger.name, trigger.description]}
310335
onSelect={() => handleBlockSelect(trigger, 'trigger')}
311336
icon={trigger.icon}
312337
bgColor={trigger.bgColor}
@@ -323,7 +348,8 @@ export function SearchModal({
323348
{workflows.map((workflow) => (
324349
<Command.Item
325350
key={workflow.id}
326-
value={workflow.name}
351+
value={`workflow-${workflow.id}`}
352+
keywords={[workflow.name]}
327353
onSelect={() => handleWorkflowSelect(workflow)}
328354
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'
329355
>
@@ -345,8 +371,8 @@ export function SearchModal({
345371
{toolOperations.map((op) => (
346372
<CommandItem
347373
key={op.id}
348-
value={op.searchValue}
349-
keywords={op.keywords}
374+
value={`operation-${op.id}`}
375+
keywords={[op.searchValue, ...(op.keywords || [])]}
350376
onSelect={() => handleToolOperationSelect(op)}
351377
icon={op.icon}
352378
bgColor={op.bgColor}
@@ -363,7 +389,8 @@ export function SearchModal({
363389
{workspaces.map((workspace) => (
364390
<Command.Item
365391
key={workspace.id}
366-
value={workspace.name}
392+
value={`workspace-${workspace.id}`}
393+
keywords={[workspace.name]}
367394
onSelect={() => handleWorkspaceSelect(workspace)}
368395
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'
369396
>
@@ -381,7 +408,8 @@ export function SearchModal({
381408
{docs.map((doc) => (
382409
<CommandItem
383410
key={doc.id}
384-
value={`${doc.name} docs documentation`}
411+
value={`doc-${doc.id}`}
412+
keywords={[doc.name, 'docs', 'documentation']}
385413
onSelect={() => handleDocSelect(doc)}
386414
icon={doc.icon}
387415
bgColor='#6B7280'
@@ -400,7 +428,8 @@ export function SearchModal({
400428
return (
401429
<Command.Item
402430
key={page.id}
403-
value={page.name}
431+
value={`page-${page.id}`}
432+
keywords={[page.name]}
404433
onSelect={() => handlePageSelect(page)}
405434
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'
406435
>

apps/sim/stores/modals/search/store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export const useSearchModalStore = create<SearchModalState>()(
129129
.filter((op) => allowedBlockTypes.has(op.blockType))
130130
.map((op) => ({
131131
id: op.id,
132-
name: `${op.serviceName}: ${op.operationName}`,
132+
name: op.operationName,
133133
searchValue: `${op.serviceName} ${op.operationName}`,
134134
icon: op.icon,
135135
bgColor: op.bgColor,

0 commit comments

Comments
 (0)