Fix nested Popover components not opening (#2293)
* fix nested `Popover`s not working * update changelog
This commit is contained in:
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Ensure the main tree and parent `Dialog` components are marked as `inert` ([#2290](https://github.com/tailwindlabs/headlessui/pull/2290))
|
||||
- Fix nested `Popover` components not opening ([#2293](https://github.com/tailwindlabs/headlessui/pull/2293))
|
||||
|
||||
## [1.7.11] - 2023-02-15
|
||||
|
||||
|
||||
@@ -2481,3 +2481,64 @@ describe('Mouse interactions', () => {
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
describe('Nested popovers', () => {
|
||||
it(
|
||||
'should be possible to nest Popover components and control them individually',
|
||||
suppressConsoleLogs(async () => {
|
||||
render(
|
||||
<Popover data-testid="popover-a">
|
||||
<Popover.Button>Toggle A</Popover.Button>
|
||||
<Popover.Panel>
|
||||
<span>Contents A</span>
|
||||
<Popover data-testid="popover-b">
|
||||
<Popover.Button>Toggle B</Popover.Button>
|
||||
<Popover.Panel>
|
||||
<span>Contents B</span>
|
||||
</Popover.Panel>
|
||||
</Popover>
|
||||
</Popover.Panel>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
// Verify that Popover B is not there yet
|
||||
expect(document.querySelector('[data-testid="popover-b"]')).toBeNull()
|
||||
|
||||
// Open Popover A
|
||||
await click(getByText('Toggle A'))
|
||||
|
||||
// Ensure Popover A is visible
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-a"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
|
||||
// Ensure Popover B is visible
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.InvisibleUnmounted },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-b"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
|
||||
// Open Popover B
|
||||
await click(getByText('Toggle B'))
|
||||
|
||||
// Ensure both popovers are open
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-a"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-b"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
@@ -393,7 +393,12 @@ let Button = forwardRefWithAs(function Button<TTag extends ElementType = typeof
|
||||
let closeOthers = groupContext?.closeOthers
|
||||
|
||||
let panelContext = usePopoverPanelContext()
|
||||
let isWithinPanel = panelContext !== null
|
||||
|
||||
// A button inside a panel will just have "close" functionality, no "open" functionality. However,
|
||||
// if a `Popover.Button` is rendered inside a `Popover` which in turn is rendered inside a
|
||||
// `Popover.Panel` (aka nested popovers), then we need to make sure that the button is able to
|
||||
// open the nested popover.
|
||||
let isWithinPanel = panelContext === null ? false : panelContext === state.panelId
|
||||
|
||||
useEffect(() => {
|
||||
if (isWithinPanel) return
|
||||
|
||||
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Ensure the main tree and parent `Dialog` components are marked as `inert` ([#2290](https://github.com/tailwindlabs/headlessui/pull/2290))
|
||||
- Fix nested `Popover` components not opening ([#2293](https://github.com/tailwindlabs/headlessui/pull/2293))
|
||||
|
||||
## [1.7.10] - 2023-02-15
|
||||
|
||||
|
||||
@@ -2574,3 +2574,64 @@ describe('Mouse interactions', () => {
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
describe('Nested popovers', () => {
|
||||
it(
|
||||
'should be possible to nest Popover components and control them individually',
|
||||
suppressConsoleLogs(async () => {
|
||||
renderTemplate(html`
|
||||
<Popover data-testid="popover-a">
|
||||
<PopoverButton>Toggle A</PopoverButton>
|
||||
<PopoverPanel>
|
||||
<span>Contents A</span>
|
||||
<Popover data-testid="popover-b">
|
||||
<PopoverButton>Toggle B</PopoverButton>
|
||||
<PopoverPanel>
|
||||
<span>Contents B</span>
|
||||
</PopoverPanel>
|
||||
</Popover>
|
||||
</PopoverPanel>
|
||||
</Popover>
|
||||
`)
|
||||
|
||||
// Verify that Popover B is not there yet
|
||||
expect(document.querySelector('[data-testid="popover-b"]')).toBeNull()
|
||||
|
||||
// Open Popover A
|
||||
await click(getByText('Toggle A'))
|
||||
|
||||
// Ensure Popover A is visible
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-a"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
|
||||
// Ensure Popover B is visible
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.InvisibleUnmounted },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-b"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
|
||||
// Open Popover B
|
||||
await click(getByText('Toggle B'))
|
||||
|
||||
// Ensure both popovers are open
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-a"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
assertPopoverPanel(
|
||||
{ state: PopoverState.Visible },
|
||||
document.querySelector(
|
||||
'[data-testid="popover-b"] [id^="headlessui-popover-panel-"]'
|
||||
) as HTMLElement
|
||||
)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
@@ -288,6 +288,11 @@ export let PopoverButton = defineComponent({
|
||||
let closeOthers = groupContext?.closeOthers
|
||||
|
||||
let panelContext = usePopoverPanelContext()
|
||||
|
||||
// A button inside a panel will just have "close" functionality, no "open" functionality.
|
||||
// However, if a `Popover.Button` is rendered inside a `Popover` which in turn is rendered
|
||||
// inside a `Popover.Panel` (aka nested popovers), then we need to make sure that the button is
|
||||
// able to open the nested popover.
|
||||
let isWithinPanel = computed(() =>
|
||||
panelContext === null ? false : panelContext.value === api.panelId.value
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user