Explorar el Código

Merge pull request #33534 from overleaf/em-fix-autocomplete-32913

Fix autocomplete dropdown closing on blur and input re-click

GitOrigin-RevId: 82f45f0f1ae9e2b3846906d962a3f16e5b2963e4
Eric Mc Sween hace 3 meses
padre
commit
e0488a8d3b

+ 3 - 0
services/web/frontend/js/shared/components/ol/ol-autocomplete.tsx

@@ -33,6 +33,7 @@ export type OLAutocompleteProps = {
   inputRef?: React.ForwardedRef<HTMLInputElement>
   expandUp?: boolean
   onClose?: () => void
+  isOpen?: boolean
 }
 
 type OLAutocompleteDisplayItem =
@@ -59,6 +60,7 @@ function OLAutocompleteInternal({
   inputRef,
   expandUp = false,
   onClose,
+  isOpen: controlledIsOpen,
 }: OLAutocompleteProps) {
   const { t } = useTranslation()
 
@@ -140,6 +142,7 @@ function OLAutocompleteInternal({
     inputValue: internalInputValue,
     items: displayItems,
     defaultHighlightedIndex: 0,
+    ...(controlledIsOpen !== undefined && { isOpen: controlledIsOpen }),
     itemToString: item => {
       if (!item) return ''
       return item.type === 'create' ? item.inputValue : item.label

+ 30 - 0
services/web/test/frontend/components/shared/ol-autocomplete.spec.tsx

@@ -60,6 +60,7 @@ function render(props: RenderProps) {
           useFuzzySearch={props.useFuzzySearch}
           expandUp={props.expandUp}
           onClose={props.onClose}
+          isOpen={props.isOpen}
         />
         <button type="submit">submit</button>
       </form>
@@ -551,6 +552,35 @@ describe('<OLAutocomplete />', function () {
     })
   })
 
+  describe('controlled isOpen prop', function () {
+    it('keeps dropdown open when input is blurred', function () {
+      render({ items: testItems, isOpen: true })
+      cy.findByRole('combobox').click()
+      cy.get('.dropdown-menu.show').should('exist')
+
+      cy.findByRole('combobox').blur()
+      cy.get('.dropdown-menu.show').should('exist')
+    })
+
+    it('keeps dropdown open when input is clicked while already open', function () {
+      render({ items: testItems, isOpen: true })
+      cy.findByRole('combobox').click()
+      cy.get('.dropdown-menu.show').should('exist')
+
+      cy.findByRole('combobox').click()
+      cy.get('.dropdown-menu.show').should('exist')
+    })
+
+    it('calls onClose when Escape is pressed', function () {
+      const closeHandler = cy.stub().as('closeHandler')
+      render({ items: testItems, isOpen: true, onClose: closeHandler })
+
+      cy.findByRole('combobox').type('{esc}')
+
+      cy.get('@closeHandler').should('have.been.calledOnce')
+    })
+  })
+
   describe('expandUp prop', function () {
     it('renders search bar before results list when expandUp is false', function () {
       render({ items: testItems, expandUp: false })