Skip to content

Commit

Permalink
✨Popover: implement native [popover] (#3601)
Browse files Browse the repository at this point in the history
and deprecated withinPortal
  • Loading branch information
oddvernes authored Aug 28, 2024
1 parent 48b11dc commit 3847778
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ export const ActivateOnClick: StoryFn<PopoverProps> = () => {
onClose={closePopover}
open={isOpen}
placement="top"
withinPortal
>
<Popover.Header>
<Popover.Title>Title</Popover.Title>
Expand Down Expand Up @@ -199,7 +198,6 @@ export const ActivateOnHover: StoryFn<PopoverProps> = () => {
onClose={handleClose}
open={isOpen}
placement="top"
withinPortal
>
<Popover.Header>
<Popover.Title>Title</Popover.Title>
Expand Down Expand Up @@ -237,7 +235,6 @@ export const WithCloseButton: StoryFn<PopoverProps> = () => {
open={isOpen}
placement="top"
trapFocus
withinPortal
>
<Popover.Header>
<Popover.Title>Title</Popover.Title>
Expand Down Expand Up @@ -297,7 +294,6 @@ export const PersistentPopover: StoryFn<PopoverProps> = () => {
open={isOpen}
placement="top"
trapFocus
withinPortal
>
<Popover.Header>
<Popover.Title>With Autocomplete</Popover.Title>
Expand Down Expand Up @@ -345,7 +341,6 @@ PersistentPopover.storyName = 'Persistent popover'
onClose={closePopover}
open={isOpen}
placement="top"
withinPortal
>
<Popover.Header>
<Popover.Title>Title</Popover.Title>
Expand Down Expand Up @@ -404,7 +399,6 @@ export const AppLauncher: StoryFn<PopoverProps> = () => {
onClose={closePopover}
placement="top"
trapFocus
withinPortal
>
<Popover.Content>
<Wrapper>
Expand Down
12 changes: 4 additions & 8 deletions packages/eds-core-react/src/components/Popover/Popover.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,15 @@ describe('Popover', () => {

await waitFor(() => expect(container).toHaveStyleRule('background', 'red'))
})
it('is visible when open is true & anchorEl is set', async () => {
it('is visible when open is true & anchorEl is set', () => {
render(
<TestPopover open placement="right-start" data-testid="popover">
<div>some random content</div>
</TestPopover>,
)
const container = screen.getByTestId('popover')
await waitFor(() => {
expect(container).toBeDefined()
})
await waitFor(() => {
expect(container).toHaveAttribute('open')
})
const container = screen.queryByTestId('popover')
expect(container).toBeDefined()
expect(container).toBeVisible()
})

it('has rendered Popover Title', async () => {
Expand Down
90 changes: 50 additions & 40 deletions packages/eds-core-react/src/components/Popover/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
mergeRefs,
useToken,
outlineTemplate,
useIsInDialog,
useIsomorphicLayoutEffect,
} from '@equinor/eds-utils'
import { popover as popoverToken } from './Popover.tokens'
import { useEds } from '../EdsProvider'
Expand All @@ -28,7 +28,6 @@ import {
useFloating,
useInteractions,
useDismiss,
FloatingPortal,
FloatingFocusManager,
} from '@floating-ui/react'

Expand All @@ -38,22 +37,35 @@ const PopoverPaper = styled(Paper)(({ theme }) => {
} = theme

return css`
position: relative;
${typographyTemplate(theme.typography)}
background: ${theme.background};
${bordersTemplate(theme.border)}
z-index: 1400;
&:focus-visible {
${outlineTemplate(paper.states.focus.outline)}
}
`
})

const StyledPopover = styled('div').withConfig({
shouldForwardProp: () => true, //workaround to avoid warning until popover gets added to react types
})<{ popover: string }>`
inset: unset;
border: 0;
padding: 0;
margin: 0;
overflow: visible;
background-color: transparent;
&::backdrop {
background-color: transparent;
}
`

const ArrowWrapper = styled.div(({ theme }) => {
return css`
position: absolute;
width: ${theme.entities.arrow.width};
height: ${theme.entities.arrow.height};
z-index: -1;
`
})

Expand Down Expand Up @@ -91,7 +103,9 @@ export type PopoverProps = {
anchorEl?: HTMLElement | null
/** Is Popover open */
open: boolean
/** initializes react portal for dropdown, default to false. */
/**
* @deprecated Popover now uses the native popover api instead of react portal. This prop will be removed in a future version
*/
withinPortal?: boolean
/** Determines whether focus should be trapped within dropdown,
* default to false. */
Expand All @@ -113,6 +127,11 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
},
ref,
) {
if (withinPortal) {
console.warn(
'Popover "withinPortal" prop has been deprecated. Popover now uses the native popover api',
)
}
const arrowRef = useRef<HTMLDivElement>(null)

const {
Expand Down Expand Up @@ -146,6 +165,14 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(

const { getFloatingProps } = useInteractions([useDismiss(context)])

useIsomorphicLayoutEffect(() => {
if (open) {
refs.floating.current?.showPopover()
} else {
refs.floating.current?.hidePopover()
}
}, [open, refs.floating])

useEffect(() => {
if (arrowRef.current) {
const staticSide = {
Expand Down Expand Up @@ -183,21 +210,16 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
}, [arrowRef.current, arrowX, arrowY, finalPlacement])

const props = {
open,
...rest,
}

const { density } = useEds()
const token = useToken({ density }, popoverToken)

//temporary fix when inside dialog. Should be replaced by popover api when it is ready
const inDialog = useIsInDialog(anchorEl)

const popover = (
<ThemeProvider theme={token}>
<PopoverPaper
elevation="overlay"
{...props}
<StyledPopover
popover="manual"
{...getFloatingProps({
ref: popoverRef,
style: {
Expand All @@ -208,39 +230,27 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
},
})}
>
<ArrowWrapper ref={arrowRef} className="arrow">
<PopoverArrow className="arrowSvg">
<path d="M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z" />
</PopoverArrow>
</ArrowWrapper>
<InnerWrapper>{children}</InnerWrapper>
</PopoverPaper>
<PopoverPaper elevation="overlay" {...props}>
<ArrowWrapper ref={arrowRef} className="arrow">
<PopoverArrow className="arrowSvg">
<path d="M0.504838 4.86885C-0.168399 4.48524 -0.168399 3.51476 0.504838 3.13115L6 8.59227e-08L6 8L0.504838 4.86885Z" />
</PopoverArrow>
</ArrowWrapper>
<InnerWrapper>{children}</InnerWrapper>
</PopoverPaper>
</StyledPopover>
</ThemeProvider>
)

return (
<>
{withinPortal && !inDialog ? (
<FloatingPortal id="eds-popover-container">
{open && trapFocus
? open && (
<FloatingFocusManager context={context} modal={true}>
{popover}
</FloatingFocusManager>
)
: open && popover}
</FloatingPortal>
) : (
<>
{trapFocus
? open && (
<FloatingFocusManager context={context} modal={true}>
{popover}
</FloatingFocusManager>
)
: open && popover}
</>
)}
{trapFocus
? open && (
<FloatingFocusManager context={context} modal={true}>
{popover}
</FloatingFocusManager>
)
: open && popover}
</>
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`Popover Matches snapshot 1`] = `
}
.c1 {
position: relative;
margin: 0;
color: var(--eds_ui__accordion_header_color, rgba(61, 61, 61, 1));
font-family: Equinor;
Expand All @@ -16,7 +17,6 @@ exports[`Popover Matches snapshot 1`] = `
text-align: left;
background: var(--eds_ui_background__default, rgba(255, 255, 255, 1));
border-radius: 4px;
z-index: 1400;
}
.c1:focus-visible {
Expand All @@ -28,7 +28,6 @@ exports[`Popover Matches snapshot 1`] = `
position: absolute;
width: 6px;
height: 8px;
z-index: -1;
}
.c5 {
Expand All @@ -55,9 +54,6 @@ exports[`Popover Matches snapshot 1`] = `
<div
class="c0 c1 c2"
data-testid="popover"
open=""
style="position: absolute; top: 14px; left: 8px;"
tabindex="-1"
>
<div
class="c3 arrow"
Expand Down

0 comments on commit 3847778

Please sign in to comment.