Skip to content

Commit

Permalink
feat(AIR-59342): add ability to render under certain element (#1416)
Browse files Browse the repository at this point in the history
* feat(AIR-59342): add ability to render under certain element

* feat(AIR-59342): added change log

* feat(AIR-59342): Added fallback state
  • Loading branch information
davidjeonprice committed Nov 17, 2023
1 parent d823d4f commit 9728046
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
10 changes: 10 additions & 0 deletions common/changes/pcln-popover/AIR-59342_2023-11-16-20-32.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "pcln-popover",
"comment": "Added ability to render popover under a certain element",
"type": "patch"
}
],
"packageName": "pcln-popover"
}
30 changes: 30 additions & 0 deletions packages/popover/src/Popover/Popover.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,24 @@ const OpenAndCloseTemplate = (args) => (
</Popover>
)

const OpenAndCloseTemplate2 = (args) => (
<>
<div id='popover-portal'>Should render here</div>
<Popover
querySelectorPortal='#popover-portal'
{...args}
renderContent={({ handleClose }) => (
<Box p={2}>
<p>Hello there!</p>
<Button onClick={handleClose}>Click me to close!</Button>
</Box>
)}
>
<Button>Open popover</Button>
</Popover>
</>
)

export const OpensOnClick = {
name: 'Tests / Opens on click',
render: OpenAndCloseTemplate.bind({}),
Expand All @@ -293,3 +311,15 @@ export const OpensOnClick = {
await new Promise((resolve) => setTimeout(resolve, 2000))
},
}

export const RendersOnSpecificArea = {
name: 'Renders on specific area',
render: OpenAndCloseTemplate2.bind({}),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const triggerBtn = canvas.getByText('Open popover')
expect(triggerBtn).toBeInTheDocument()
await userEvent.click(triggerBtn)
await new Promise((resolve) => setTimeout(resolve, 2000))
},
}
16 changes: 14 additions & 2 deletions packages/popover/src/PopoverContent/PopoverContent.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react'
import React, { useCallback, useEffect, useLayoutEffect, useState } from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import styled, { ThemeConsumer } from 'styled-components'
Expand Down Expand Up @@ -44,6 +44,7 @@ function PopoverContent({
styles,
width,
zIndex,
querySelectorPortal,
...props
}) {
const handleKeyUp = useCallback(
Expand All @@ -57,13 +58,22 @@ function PopoverContent({
[onCloseRequest]
)

const [portalSelector, setPortalSelector] = useState(querySelectorPortal)

useEffect(() => {
window.addEventListener('keyup', handleKeyUp, false)
return () => {
window.removeEventListener('keyup', handleKeyUp, false)
}
}, [handleKeyUp])

// Fallback when cannot find an element
useLayoutEffect(() => {
if (!document.querySelector(portalSelector)) {
setPortalSelector('body')
}
}, [querySelectorPortal])

const getBorderColorName = (color, borderColor) => {
let borderColorName = borderColor

Expand Down Expand Up @@ -142,7 +152,7 @@ function PopoverContent({
)}
</>,
// Append each instance of the Popover as portal directly to the body
document.querySelector('body')
document.querySelector(portalSelector)
)
}

Expand All @@ -164,13 +174,15 @@ PopoverContent.propTypes = {
trapFocus: PropTypes.bool,
hideArrow: PropTypes.bool,
hideOverlay: PropTypes.bool,
querySelectorPortal: PropTypes.string,
}

PopoverContent.defaultProps = {
p: 2,
placement: 'top',
zIndex: 102,
width: 400,
querySelectorPortal: 'body',
}

export default PopoverContent

0 comments on commit 9728046

Please sign in to comment.