diff --git a/src/Details.js b/src/Details.js index 8cbb0020eb0..e9b0e190488 100644 --- a/src/Details.js +++ b/src/Details.js @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useState, useEffect, useRef} from 'react' import PropTypes from 'prop-types' import styled from 'styled-components' import {COMMON} from './constants' @@ -18,29 +18,31 @@ function getRenderer(children) { function DetailsBase({children, overlay, render = getRenderer(children), defaultOpen = false, ...rest}) { const [open, setOpen] = useState(defaultOpen) + const ref = useRef(null) - useEffect( - () => { - if (overlay && open) { - document.addEventListener('click', closeMenu) - return () => { - document.removeEventListener('click', closeMenu) - } + useEffect(() => { + if (overlay && open) { + document.addEventListener('click', closeMenu) + return () => { + document.removeEventListener('click', closeMenu) } - }, - [open, overlay] - ) + } + }, [open, overlay]) function toggle(event) { setOpen(event.target.open) } function closeMenu(event) { - setOpen(false) + // only close the menu if we're clicking outside + if (event && event.target.closest('details') !== ref.current) { + setOpen(false) + document.removeEventListener('click', closeMenu) + } } return ( - + {render({open})} ) diff --git a/src/__tests__/Details.js b/src/__tests__/Details.js index cc8af2b197e..f485db2bf2e 100644 --- a/src/__tests__/Details.js +++ b/src/__tests__/Details.js @@ -40,6 +40,47 @@ describe('Details', () => { expect(dom.hasAttribute('open')).toEqual(false) expect(summary.text()).toEqual('open') + summary.simulate('click') + }) + + it('Toggles when you click outside', () => { + const wrapper = mount(
{({open}) => {open ? 'close' : 'open'}}
) + + document.body.click() + + const dom = wrapper.getDOMNode() + const summary = wrapper.find('summary') + + expect(dom.hasAttribute('open')).toEqual(false) + expect(summary.text()).toEqual('open') + + wrapper.unmount() + }) + + xit('Does not toggle or prevent click events when you click inside', () => { + const wrapper = mount( +
+ {({open}) => ( + <> + {open ? 'close' : 'open'} +
content
+ + )} +
+ ) + + document.body.click() + + const dom = wrapper.getDOMNode() + const content = dom.querySelector('div') + + let clickEvent + content.addEventListener('click', event => (clickEvent = event)) + content.click() + + expect(dom.hasAttribute('open')).toEqual(true) + expect(clickEvent.defaultPrevented).toBe(false) + wrapper.unmount() }) }) diff --git a/src/__tests__/Dropdown.js b/src/__tests__/Dropdown.js index fba9f876fbf..b2c6d75a1e8 100644 --- a/src/__tests__/Dropdown.js +++ b/src/__tests__/Dropdown.js @@ -38,18 +38,18 @@ describe('Dropdown.Menu', () => { expect( render( -
  • 1
  • -
  • 2
  • -
  • 3
  • +
  • 1
  • +
  • 2
  • +
  • 3
  • ) ).toMatchSnapshot() expect( render( -
  • 1
  • -
  • 2
  • -
  • 3
  • +
  • 1
  • +
  • 2
  • +
  • 3
  • ) ).toMatchSnapshot()