Skip to content

Commit 44dda1a

Browse files
committed
perf: always render command palette for instant opening
1 parent 0603101 commit 44dda1a

File tree

1 file changed

+177
-175
lines changed
  • apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/search-modal

1 file changed

+177
-175
lines changed

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

Lines changed: 177 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -243,187 +243,189 @@ export function SearchModal({
243243
aria-hidden={!open}
244244
/>
245245

246-
{/* Command palette - only render when open to ensure SVG gradients work */}
247-
{open && (
248-
<div
249-
role='dialog'
250-
aria-modal={true}
251-
aria-label='Search'
252-
className='-translate-x-1/2 fixed top-[15%] left-1/2 z-50 w-[500px] overflow-hidden rounded-[12px] border border-[var(--border)] bg-[var(--surface-4)] shadow-lg'
253-
>
254-
<Command label='Search' filter={customFilter}>
255-
<Command.Input
256-
ref={inputRef}
257-
autoFocus
258-
onValueChange={handleSearchChange}
259-
placeholder='Search anything...'
260-
className='w-full border-0 border-[var(--border)] border-b bg-transparent px-[12px] py-[10px] font-base text-[15px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none'
261-
/>
262-
<Command.List className='scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent max-h-[400px] overflow-y-auto p-[8px]'>
263-
<Command.Empty className='flex items-center justify-center px-[16px] py-[24px] text-[15px] text-[var(--text-subtle)]'>
264-
No results found.
265-
</Command.Empty>
266-
267-
{showBlocks && (
268-
<Command.Group heading='Blocks' className={groupHeadingClassName}>
269-
{blocks.map((block) => (
270-
<CommandItem
271-
key={block.id}
272-
value={block.name}
273-
keywords={[block.description]}
274-
onSelect={() => handleBlockSelect(block, 'block')}
275-
icon={block.icon}
276-
bgColor={block.bgColor}
277-
showColoredIcon
278-
>
279-
{block.name}
280-
</CommandItem>
281-
))}
282-
</Command.Group>
283-
)}
284-
285-
{showTools && (
286-
<Command.Group heading='Tools' className={groupHeadingClassName}>
287-
{tools.map((tool) => (
288-
<CommandItem
289-
key={tool.id}
290-
value={tool.name}
291-
keywords={[tool.description]}
292-
onSelect={() => handleBlockSelect(tool, 'tool')}
293-
icon={tool.icon}
294-
bgColor={tool.bgColor}
295-
showColoredIcon
296-
>
297-
{tool.name}
298-
</CommandItem>
299-
))}
300-
</Command.Group>
301-
)}
302-
303-
{showTriggers && (
304-
<Command.Group heading='Triggers' className={groupHeadingClassName}>
305-
{triggers.map((trigger) => (
306-
<CommandItem
307-
key={trigger.id}
308-
value={trigger.name}
309-
keywords={[trigger.description]}
310-
onSelect={() => handleBlockSelect(trigger, 'trigger')}
311-
icon={trigger.icon}
312-
bgColor={trigger.bgColor}
313-
showColoredIcon
314-
>
315-
{trigger.name}
316-
</CommandItem>
317-
))}
318-
</Command.Group>
319-
)}
320-
321-
{workflows.length > 0 && (
322-
<Command.Group heading='Workflows' className={groupHeadingClassName}>
323-
{workflows.map((workflow) => (
324-
<Command.Item
325-
key={workflow.id}
326-
value={workflow.name}
327-
onSelect={() => handleWorkflowSelect(workflow)}
328-
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'
329-
>
330-
<div
331-
className='h-[14px] w-[14px] flex-shrink-0 rounded-[3px]'
332-
style={{ backgroundColor: workflow.color }}
333-
/>
334-
<span className='truncate font-medium text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]'>
335-
{workflow.name}
336-
{workflow.isCurrent && ' (current)'}
337-
</span>
338-
</Command.Item>
339-
))}
340-
</Command.Group>
341-
)}
342-
343-
{showToolOperations && (
344-
<Command.Group heading='Tool Operations' className={groupHeadingClassName}>
345-
{toolOperations.map((op) => (
346-
<CommandItem
347-
key={op.id}
348-
value={op.searchValue}
349-
keywords={op.keywords}
350-
onSelect={() => handleToolOperationSelect(op)}
351-
icon={op.icon}
352-
bgColor={op.bgColor}
353-
showColoredIcon
354-
>
355-
{op.name}
356-
</CommandItem>
357-
))}
358-
</Command.Group>
359-
)}
360-
361-
{workspaces.length > 0 && (
362-
<Command.Group heading='Workspaces' className={groupHeadingClassName}>
363-
{workspaces.map((workspace) => (
246+
{/* Command palette - always rendered for instant opening, hidden with CSS */}
247+
<div
248+
role='dialog'
249+
aria-modal={open}
250+
aria-hidden={!open}
251+
aria-label='Search'
252+
className={cn(
253+
'-translate-x-1/2 fixed top-[15%] left-1/2 z-50 w-[500px] overflow-hidden rounded-[12px] border border-[var(--border)] bg-[var(--surface-4)] shadow-lg',
254+
open ? 'visible opacity-100' : 'invisible opacity-0'
255+
)}
256+
>
257+
<Command label='Search' filter={customFilter}>
258+
<Command.Input
259+
ref={inputRef}
260+
autoFocus
261+
onValueChange={handleSearchChange}
262+
placeholder='Search anything...'
263+
className='w-full border-0 border-[var(--border)] border-b bg-transparent px-[12px] py-[10px] font-base text-[15px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none'
264+
/>
265+
<Command.List className='scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent max-h-[400px] overflow-y-auto p-[8px]'>
266+
<Command.Empty className='flex items-center justify-center px-[16px] py-[24px] text-[15px] text-[var(--text-subtle)]'>
267+
No results found.
268+
</Command.Empty>
269+
270+
{showBlocks && (
271+
<Command.Group heading='Blocks' className={groupHeadingClassName}>
272+
{blocks.map((block) => (
273+
<CommandItem
274+
key={block.id}
275+
value={block.name}
276+
keywords={[block.description]}
277+
onSelect={() => handleBlockSelect(block, 'block')}
278+
icon={block.icon}
279+
bgColor={block.bgColor}
280+
showColoredIcon
281+
>
282+
{block.name}
283+
</CommandItem>
284+
))}
285+
</Command.Group>
286+
)}
287+
288+
{showTools && (
289+
<Command.Group heading='Tools' className={groupHeadingClassName}>
290+
{tools.map((tool) => (
291+
<CommandItem
292+
key={tool.id}
293+
value={tool.name}
294+
keywords={[tool.description]}
295+
onSelect={() => handleBlockSelect(tool, 'tool')}
296+
icon={tool.icon}
297+
bgColor={tool.bgColor}
298+
showColoredIcon
299+
>
300+
{tool.name}
301+
</CommandItem>
302+
))}
303+
</Command.Group>
304+
)}
305+
306+
{showTriggers && (
307+
<Command.Group heading='Triggers' className={groupHeadingClassName}>
308+
{triggers.map((trigger) => (
309+
<CommandItem
310+
key={trigger.id}
311+
value={trigger.name}
312+
keywords={[trigger.description]}
313+
onSelect={() => handleBlockSelect(trigger, 'trigger')}
314+
icon={trigger.icon}
315+
bgColor={trigger.bgColor}
316+
showColoredIcon
317+
>
318+
{trigger.name}
319+
</CommandItem>
320+
))}
321+
</Command.Group>
322+
)}
323+
324+
{workflows.length > 0 && (
325+
<Command.Group heading='Workflows' className={groupHeadingClassName}>
326+
{workflows.map((workflow) => (
327+
<Command.Item
328+
key={workflow.id}
329+
value={workflow.name}
330+
onSelect={() => handleWorkflowSelect(workflow)}
331+
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'
332+
>
333+
<div
334+
className='h-[14px] w-[14px] flex-shrink-0 rounded-[3px]'
335+
style={{ backgroundColor: workflow.color }}
336+
/>
337+
<span className='truncate font-medium text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]'>
338+
{workflow.name}
339+
{workflow.isCurrent && ' (current)'}
340+
</span>
341+
</Command.Item>
342+
))}
343+
</Command.Group>
344+
)}
345+
346+
{showToolOperations && (
347+
<Command.Group heading='Tool Operations' className={groupHeadingClassName}>
348+
{toolOperations.map((op) => (
349+
<CommandItem
350+
key={op.id}
351+
value={op.searchValue}
352+
keywords={op.keywords}
353+
onSelect={() => handleToolOperationSelect(op)}
354+
icon={op.icon}
355+
bgColor={op.bgColor}
356+
showColoredIcon
357+
>
358+
{op.name}
359+
</CommandItem>
360+
))}
361+
</Command.Group>
362+
)}
363+
364+
{workspaces.length > 0 && (
365+
<Command.Group heading='Workspaces' className={groupHeadingClassName}>
366+
{workspaces.map((workspace) => (
367+
<Command.Item
368+
key={workspace.id}
369+
value={workspace.name}
370+
onSelect={() => handleWorkspaceSelect(workspace)}
371+
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'
372+
>
373+
<span className='truncate font-medium text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]'>
374+
{workspace.name}
375+
{workspace.isCurrent && ' (current)'}
376+
</span>
377+
</Command.Item>
378+
))}
379+
</Command.Group>
380+
)}
381+
382+
{showDocs && (
383+
<Command.Group heading='Docs' className={groupHeadingClassName}>
384+
{docs.map((doc) => (
385+
<CommandItem
386+
key={doc.id}
387+
value={`${doc.name} docs documentation`}
388+
onSelect={() => handleDocSelect(doc)}
389+
icon={doc.icon}
390+
bgColor='#6B7280'
391+
showColoredIcon
392+
>
393+
{doc.name}
394+
</CommandItem>
395+
))}
396+
</Command.Group>
397+
)}
398+
399+
{pages.length > 0 && (
400+
<Command.Group heading='Pages' className={groupHeadingClassName}>
401+
{pages.map((page) => {
402+
const Icon = page.icon
403+
return (
364404
<Command.Item
365-
key={workspace.id}
366-
value={workspace.name}
367-
onSelect={() => handleWorkspaceSelect(workspace)}
405+
key={page.id}
406+
value={page.name}
407+
onSelect={() => handlePageSelect(page)}
368408
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'
369409
>
410+
<div className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center'>
411+
<Icon className='h-[14px] w-[14px] text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]' />
412+
</div>
370413
<span className='truncate font-medium text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]'>
371-
{workspace.name}
372-
{workspace.isCurrent && ' (current)'}
414+
{page.name}
373415
</span>
374-
</Command.Item>
375-
))}
376-
</Command.Group>
377-
)}
378-
379-
{showDocs && (
380-
<Command.Group heading='Docs' className={groupHeadingClassName}>
381-
{docs.map((doc) => (
382-
<CommandItem
383-
key={doc.id}
384-
value={`${doc.name} docs documentation`}
385-
onSelect={() => handleDocSelect(doc)}
386-
icon={doc.icon}
387-
bgColor='#6B7280'
388-
showColoredIcon
389-
>
390-
{doc.name}
391-
</CommandItem>
392-
))}
393-
</Command.Group>
394-
)}
395-
396-
{pages.length > 0 && (
397-
<Command.Group heading='Pages' className={groupHeadingClassName}>
398-
{pages.map((page) => {
399-
const Icon = page.icon
400-
return (
401-
<Command.Item
402-
key={page.id}
403-
value={page.name}
404-
onSelect={() => handlePageSelect(page)}
405-
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'
406-
>
407-
<div className='relative flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center'>
408-
<Icon className='h-[14px] w-[14px] text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]' />
409-
</div>
410-
<span className='truncate font-medium text-[var(--text-tertiary)] group-aria-selected:text-[var(--text-primary)]'>
411-
{page.name}
416+
{page.shortcut && (
417+
<span className='ml-auto flex-shrink-0 font-medium text-[13px] text-[var(--text-subtle)]'>
418+
{page.shortcut}
412419
</span>
413-
{page.shortcut && (
414-
<span className='ml-auto flex-shrink-0 font-medium text-[13px] text-[var(--text-subtle)]'>
415-
{page.shortcut}
416-
</span>
417-
)}
418-
</Command.Item>
419-
)
420-
})}
421-
</Command.Group>
422-
)}
423-
</Command.List>
424-
</Command>
425-
</div>
426-
)}
420+
)}
421+
</Command.Item>
422+
)
423+
})}
424+
</Command.Group>
425+
)}
426+
</Command.List>
427+
</Command>
428+
</div>
427429
</>,
428430
document.body
429431
)

0 commit comments

Comments
 (0)