Skip to content

Commit

Permalink
Ensure interactability with Popover.Panel contents in static mode (#857)
Browse files Browse the repository at this point in the history
* ensure interactability with Popover.Panel contents in static mode

* update changelog
  • Loading branch information
RobinMalfait authored Oct 8, 2021
1 parent f9e0d30 commit fd9a2d2
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Stop the event from propagating in the `Popover` component ([#798](https://github.com/tailwindlabs/headlessui/pull/798))
- Allow to click on elements inside a `Dialog.Overlay` ([#816](https://github.com/tailwindlabs/headlessui/pull/816))
- Ensure interactability with `Popover.Panel` contents when using the `static` prop ([#857](https://github.com/tailwindlabs/headlessui/pull/857))

## [Unreleased - Vue]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { createElement, useEffect, useRef } from 'react'
import { render } from '@testing-library/react'
import { render, screen } from '@testing-library/react'

import { Popover } from './popover'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
Expand Down Expand Up @@ -2125,4 +2125,78 @@ describe('Mouse interactions', () => {
assertActiveElement(getPopoverButton())
})
)

it(
'should not close the Popover when clicking on a focusable element inside a static Popover.Panel',
suppressConsoleLogs(async () => {
let clickFn = jest.fn()

render(
<Popover>
<Popover.Button>Open</Popover.Button>
<Popover.Panel static>
<button onClick={clickFn}>btn</button>
</Popover.Panel>
</Popover>
)

// Open the popover
await click(getPopoverButton())

// The button should not close the popover
await click(getByText('btn'))

// Verify it is still open
assertPopoverButton({ state: PopoverState.Visible })

// Verify we actually clicked the button
expect(clickFn).toHaveBeenCalledTimes(1)
})
)

it(
'should not close the Popover when clicking on a non-focusable element inside a static Popover.Panel',
suppressConsoleLogs(async () => {
render(
<Popover>
<Popover.Button>Open</Popover.Button>
<Popover.Panel static>
<span>element</span>
</Popover.Panel>
</Popover>
)

// Open the popover
await click(getPopoverButton())

// The element should not close the popover
await click(getByText('element'))

// Verify it is still open
assertPopoverButton({ state: PopoverState.Visible })
})
)

it(
'should close the Popover when clicking outside of a static Popover.Panel',
suppressConsoleLogs(async () => {
render(
<Popover>
<Popover.Button>Open</Popover.Button>
<Popover.Panel static>
<span>element</span>
</Popover.Panel>
</Popover>
)

// Open the popover
await click(getPopoverButton())

// The element should close the popover
await click(document.body)

// Verify it is still open
assertPopoverButton({ state: PopoverState.InvisibleHidden })
})
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,12 @@ let Panel = forwardRefWithAs(function Panel<TTag extends ElementType = typeof DE

// Unlink on "unmount" children
useEffect(() => {
if (props.static) return

if (state.popoverState === PopoverStates.Closed && (props.unmount ?? true)) {
dispatch({ type: ActionTypes.SetPanel, panel: null })
}
}, [state.popoverState, props.unmount, dispatch])
}, [state.popoverState, props.unmount, props.static, dispatch])

// Move focus within panel
useEffect(() => {
Expand Down
77 changes: 77 additions & 0 deletions packages/@headlessui-vue/src/components/popover/popover.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2323,4 +2323,81 @@ describe('Mouse interactions', () => {
assertActiveElement(getPopoverButton())
})
)

it(
'should not close the Popover when clicking on a focusable element inside a static PopoverPanel',
suppressConsoleLogs(async () => {
let clickFn = jest.fn()

renderTemplate({
template: html`
<Popover>
<PopoverButton>Open</PopoverButton>
<PopoverPanel static>
<button @click="clickFn">btn</button>
</PopoverPanel>
</Popover>
`,
setup: () => ({ clickFn }),
})

// Open the popover
await click(getPopoverButton())

// The button should not close the popover
await click(getByText('btn'))

// Verify it is still open
assertPopoverButton({ state: PopoverState.Visible })

// Verify we actually clicked the button
expect(clickFn).toHaveBeenCalledTimes(1)
})
)

it(
'should not close the Popover when clicking on a non-focusable element inside a static PopoverPanel',
suppressConsoleLogs(async () => {
renderTemplate(html`
<Popover>
<PopoverButton>Open</PopoverButton>
<PopoverPanel static>
<span>element</span>
</PopoverPanel>
</Popover>
`)

// Open the popover
await click(getPopoverButton())

// The element should not close the popover
await click(getByText('element'))

// Verify it is still open
assertPopoverButton({ state: PopoverState.Visible })
})
)

it(
'should close the Popover when clicking outside of a static PopoverPanel',
suppressConsoleLogs(async () => {
renderTemplate(html`
<Popover>
<PopoverButton>Open</PopoverButton>
<PopoverPanel static>
<span>element</span>
</PopoverPanel>
</Popover>
`)

// Open the popover
await click(getPopoverButton())

// The element should close the popover
await click(document.body)

// Verify it is still open
assertPopoverButton({ state: PopoverState.InvisibleHidden })
})
)
})

0 comments on commit fd9a2d2

Please sign in to comment.