diff --git a/web-app/src/containers/ModelCombobox.tsx b/web-app/src/containers/ModelCombobox.tsx
index 7bd6672e7..9b8144ed3 100644
--- a/web-app/src/containers/ModelCombobox.tsx
+++ b/web-app/src/containers/ModelCombobox.tsx
@@ -182,8 +182,9 @@ function useKeyboardNavigation(
onModelSelect(filteredModels[highlightedIndex])
}
break
- case 'ArrowRight':
- case 'ArrowLeft':
+ case 'Escape':
+ e.preventDefault()
+ e.stopPropagation()
setOpen(false)
setHighlightedIndex(-1)
break
@@ -195,11 +196,6 @@ function useKeyboardNavigation(
e.preventDefault()
setHighlightedIndex(filteredModels.length - 1)
break
- case 'Escape':
- e.preventDefault()
- setOpen(false)
- setHighlightedIndex(-1)
- break
}
}, [open, setOpen, models.length, filteredModels, highlightedIndex, setHighlightedIndex, onModelSelect])
@@ -216,6 +212,7 @@ type ModelComboboxProps = {
placeholder?: string
disabled?: boolean
className?: string
+ onOpenChange?: (open: boolean) => void
}
export function ModelCombobox({
@@ -228,6 +225,7 @@ export function ModelCombobox({
placeholder = 'Type or select a model...',
disabled = false,
className,
+ onOpenChange,
}: ModelComboboxProps) {
const [open, setOpen] = useState(false)
const [inputValue, setInputValue] = useState(value)
@@ -242,6 +240,11 @@ export function ModelCombobox({
setInputValue(value)
}, [value])
+ // Notify parent when open state changes
+ useEffect(() => {
+ onOpenChange?.(open)
+ }, [open, onOpenChange])
+
// Hook for the dropdown position
const { dropdownPosition } = useDropdownPosition(open, containerRef)
diff --git a/web-app/src/containers/__tests__/ModelCombobox.test.tsx b/web-app/src/containers/__tests__/ModelCombobox.test.tsx
index 1b91c3712..38f9b97c8 100644
--- a/web-app/src/containers/__tests__/ModelCombobox.test.tsx
+++ b/web-app/src/containers/__tests__/ModelCombobox.test.tsx
@@ -487,28 +487,4 @@ describe('ModelCombobox', () => {
expect(localMockOnChange).toHaveBeenCalledWith('gpt-3.5-turbo')
})
-
- it('closes dropdown with ArrowLeft key', async () => {
- const user = userEvent.setup()
- render()
-
- const input = screen.getByRole('textbox')
- input.focus()
-
- // ArrowDown should open dropdown
- await user.keyboard('{ArrowDown}')
-
- await waitFor(() => {
- const dropdown = document.querySelector('[data-dropdown="model-combobox"]')
- expect(dropdown).toBeInTheDocument()
- })
-
- // ArrowLeft should close dropdown
- await user.keyboard('{ArrowLeft}')
-
- await waitFor(() => {
- const dropdown = document.querySelector('[data-dropdown="model-combobox"]')
- expect(dropdown).not.toBeInTheDocument()
- })
- })
})
diff --git a/web-app/src/containers/dialogs/AddModel.tsx b/web-app/src/containers/dialogs/AddModel.tsx
index dc0eac244..a633867f6 100644
--- a/web-app/src/containers/dialogs/AddModel.tsx
+++ b/web-app/src/containers/dialogs/AddModel.tsx
@@ -26,6 +26,7 @@ export const DialogAddModel = ({ provider, trigger }: DialogAddModelProps) => {
const { updateProvider } = useModelProvider()
const [modelId, setModelId] = useState('')
const [open, setOpen] = useState(false)
+ const [isComboboxOpen, setIsComboboxOpen] = useState(false)
// Fetch models from provider API (API key is optional)
const { models, loading, error, refetch } = useProviderModels(
@@ -68,7 +69,13 @@ export const DialogAddModel = ({ provider, trigger }: DialogAddModelProps) => {
)}
-
+ {
+ if (isComboboxOpen) {
+ e.preventDefault()
+ }
+ }}
+ >
{t('providers:addModel.title')}
@@ -95,6 +102,7 @@ export const DialogAddModel = ({ provider, trigger }: DialogAddModelProps) => {
error={error}
onRefresh={refetch}
placeholder={t('providers:addModel.enterModelId')}
+ onOpenChange={setIsComboboxOpen}
/>