@@ -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