Skip to content

Commit d022a55

Browse files
committed
feat(tool-input): add chevron affordance and keyboard nav for MCP server drill-down
1 parent 28798da commit d022a55

File tree

2 files changed

+32
-2
lines changed
  • apps/sim
    • app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input
    • components/emcn/components/combobox

2 files changed

+32
-2
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/tool-input.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type React from 'react'
22
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
33
import { createLogger } from '@sim/logger'
4-
import { ArrowLeft, Loader2, ServerIcon, WrenchIcon, XIcon } from 'lucide-react'
4+
import { ArrowLeft, ChevronRight, Loader2, ServerIcon, WrenchIcon, XIcon } from 'lucide-react'
55
import { useParams } from 'next/navigation'
66
import {
77
Badge,
@@ -1426,6 +1426,9 @@ export const ToolInput = memo(function ToolInput({
14261426
label: `${serverName} (${toolCount} tools)`,
14271427
value: `mcp-server-folder-${serverId}`,
14281428
iconElement: createToolIcon('#6366F1', ServerIcon),
1429+
suffixElement: (
1430+
<ChevronRight className='h-[12px] w-[12px] text-[var(--text-tertiary)]' />
1431+
),
14291432
onSelect: () => {
14301433
setMcpServerDrilldown(serverId)
14311434
},
@@ -1542,6 +1545,7 @@ export const ToolInput = memo(function ToolInput({
15421545
maxHeight={240}
15431546
emptyMessage='No tools found'
15441547
onOpenChange={handleComboboxOpenChange}
1548+
onArrowLeft={mcpServerDrilldown ? () => setMcpServerDrilldown(null) : undefined}
15451549
/>
15461550

15471551
{selectedTools.length > 0 &&

apps/sim/components/emcn/components/combobox/combobox.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export type ComboboxOption = {
5555
disabled?: boolean
5656
/** When true, keep the dropdown open after selecting this option */
5757
keepOpen?: boolean
58+
/** Optional element rendered at the trailing end of the option (e.g. chevron for folders) */
59+
suffixElement?: ReactNode
5860
}
5961

6062
/**
@@ -109,6 +111,8 @@ export interface ComboboxProps
109111
error?: string | null
110112
/** Callback when popover open state changes */
111113
onOpenChange?: (open: boolean) => void
114+
/** Callback when ArrowLeft is pressed while dropdown is open (for folder back-navigation) */
115+
onArrowLeft?: () => void
112116
/** Enable search input in dropdown (useful for multiselect) */
113117
searchable?: boolean
114118
/** Placeholder for search input */
@@ -160,6 +164,7 @@ const Combobox = memo(
160164
isLoading = false,
161165
error = null,
162166
onOpenChange,
167+
onArrowLeft,
163168
searchable = false,
164169
searchPlaceholder = 'Search...',
165170
align = 'start',
@@ -386,8 +391,25 @@ const Combobox = memo(
386391
setHighlightedIndex((prev) => (prev > 0 ? prev - 1 : filteredOptions.length - 1))
387392
}
388393
}
394+
395+
if (e.key === 'ArrowRight') {
396+
if (open && highlightedIndex >= 0) {
397+
const highlightedOption = filteredOptions[highlightedIndex]
398+
if (highlightedOption?.keepOpen && highlightedOption?.onSelect) {
399+
e.preventDefault()
400+
highlightedOption.onSelect()
401+
}
402+
}
403+
}
404+
405+
if (e.key === 'ArrowLeft') {
406+
if (open && onArrowLeft) {
407+
e.preventDefault()
408+
onArrowLeft()
409+
}
410+
}
389411
},
390-
[disabled, open, highlightedIndex, filteredOptions, handleSelect, editable, inputRef]
412+
[disabled, open, highlightedIndex, filteredOptions, handleSelect, editable, inputRef, onArrowLeft]
391413
)
392414

393415
/**
@@ -600,6 +622,8 @@ const Combobox = memo(
600622
if (
601623
e.key === 'ArrowDown' ||
602624
e.key === 'ArrowUp' ||
625+
e.key === 'ArrowRight' ||
626+
e.key === 'ArrowLeft' ||
603627
e.key === 'Enter' ||
604628
e.key === 'Escape'
605629
) {
@@ -699,6 +723,7 @@ const Combobox = memo(
699723
<span className='flex-1 truncate text-[var(--text-primary)]'>
700724
{option.label}
701725
</span>
726+
{option.suffixElement}
702727
{multiSelect && isSelected && (
703728
<Check className='ml-[8px] h-[12px] w-[12px] flex-shrink-0 text-[var(--text-primary)]' />
704729
)}
@@ -772,6 +797,7 @@ const Combobox = memo(
772797
<span className='flex-1 truncate text-[var(--text-primary)]'>
773798
{option.label}
774799
</span>
800+
{option.suffixElement}
775801
{multiSelect && isSelected && (
776802
<Check className='ml-[8px] h-[12px] w-[12px] flex-shrink-0 text-[var(--text-primary)]' />
777803
)}

0 commit comments

Comments
 (0)