WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.51k stars 4.2k forks source link

Dropover / Popover does not close on outside click without focus #23298

Open joshuatf opened 4 years ago

joshuatf commented 4 years ago

Describe the bug If the Dropdown component (which uses Popover) does not receive focus, clicking outside will not close the popover.

This is problematic when we do not want to focus the contents of the dropdown immediately.

To reproduce Steps to reproduce the behavior:

  1. Create a dropdown with a toggle that's an input box.
<Dropdown
    focusOnMount={ false }
    renderToggle={ ( { isOpen, onToggle } ) => (
        <input type="text" />
    ) }
    renderContent={ ( { onToggle } ) => (
        <div>Dropdown content</div>
    ) }
/>
  1. Click on the toggle area (input).
  2. Click outside the dropdown.
  3. Note that the popover is not closed.
  4. Click on the popover area and click outside again.
  5. Note that the popover is now closed.

Expected behavior Expected the popover or dropdown to still close without receiving focus first.

Screenshots Screen Recording 2020-06-19 at 8 53 34 AM

tellthemachines commented 4 years ago

This happens because the component that checks for focus/click outside uses the blur event to trigger closure of the dropdown, so if it's never focused, it won't know that a click is happening outside of it. This is the intended behaviour of the component, so in that sense, it isn't a bug.

You could perhaps look into using the Popover component instead of the Dropdown, as that allows you to customise the onFocusOutside handler so you may be able to achieve the intended functionality that way. The Block Toolbar is an example of a component leveraging Popover for some pretty custom focus behaviour.

One thing is puzzling me though. With the example above, the dropdown will close if the user clicks the input field again. Is that the intended outcome? It seems weird to have an input serve as a toggle.

Another thing to consider in this example is how to access the dropdown with keyboard navigation. You'll need a custom handler for it, as the popover content doesn't usually come straight after the toggle in the DOM order.