admin管理员组文章数量:1404924
I need to implement a Popover primitive that always appear on top of all other elements in the page, I tried to see if some well known solutions have this implemented but it seems in all cases the Popover is added to the bottom of the Page but still z-index
is still in use:
For example:
- shadcn popover
- mui popover
- radix popover
Implementing a simple Popover is not that difficult but doing it with plain CSS might have the same issues as the ones above
- It might need
z-index
to be set in most cases - It might not be correctly positioned if its position is
fixed
and it is inside a container that have a css transform, since a new stacking context might have been created. - It might be shown inside a container with overflow auto or hidden.
Despite those issues a CSS only popover offers a very simple API and it is very easy to create.
Here is an example of the simple API I'm looking for
// the Overlay is a controlled component so the
// fact that is shown or not is controlled by the
// open property
<CSSOverlay open={isOpen}>
<div>Content here</div>
</CSSOverlay>
But most of the examples I've found go for something like
<SomeOverlay open={isOpen} style={{ zIndex: 100000 /* some arbitrary hight number no other popover will use, or at least we hope it won't */ }}>
<div>Content here</div>
</SomeOverlay>
or appending it to the body, which might still have z-index issues, and now might also have issues accessing content inside React Providers as context might not be shared with it
<SomeOverlay open={isOpen} appendToBody={true}>
<div>Content here</div>
</SomeOverlay>
Here is an example of a the CSS Popover with z-index issues
Full disclosure: This is a re-write of a now closed question posted here: What are the downsides or potential drawbacks of using `popover` attribute to create overlays, like tooltips, popovers and dialogs I've modified
I need to implement a Popover primitive that always appear on top of all other elements in the page, I tried to see if some well known solutions have this implemented but it seems in all cases the Popover is added to the bottom of the Page but still z-index
is still in use:
For example:
- shadcn popover
- mui popover
- radix popover
Implementing a simple Popover is not that difficult but doing it with plain CSS might have the same issues as the ones above
- It might need
z-index
to be set in most cases - It might not be correctly positioned if its position is
fixed
and it is inside a container that have a css transform, since a new stacking context might have been created. - It might be shown inside a container with overflow auto or hidden.
Despite those issues a CSS only popover offers a very simple API and it is very easy to create.
Here is an example of the simple API I'm looking for
// the Overlay is a controlled component so the
// fact that is shown or not is controlled by the
// open property
<CSSOverlay open={isOpen}>
<div>Content here</div>
</CSSOverlay>
But most of the examples I've found go for something like
<SomeOverlay open={isOpen} style={{ zIndex: 100000 /* some arbitrary hight number no other popover will use, or at least we hope it won't */ }}>
<div>Content here</div>
</SomeOverlay>
or appending it to the body, which might still have z-index issues, and now might also have issues accessing content inside React Providers as context might not be shared with it
<SomeOverlay open={isOpen} appendToBody={true}>
<div>Content here</div>
</SomeOverlay>
Here is an example of a the CSS Popover with z-index issues
Full disclosure: This is a re-write of a now closed question posted here: What are the downsides or potential drawbacks of using `popover` attribute to create overlays, like tooltips, popovers and dialogs I've modified
Share Improve this question asked Mar 24 at 1:25 roy riojasroy riojas 2,4963 gold badges28 silver badges30 bronze badges1 Answer
Reset to default 0A light at the end of the tunnel. The popover
attribute
I think I've found a solution that doesn't suffer from any of the z-index issues or wrong positioning on new stacking contexts :
https://developer.mozilla./en-US/docs/Web/HTML/Global_attributes/popover
Apparently the popover
attribute is widely available now so I went ahead and created a super simple Overlay
like this:
import { ComponentProps, FC, useEffect, useRef } from "react";
export type OverlayProps = ComponentProps<"div"> & {
open: boolean;
};
export const Overlay: FC<OverlayProps> = ({ children, open, ...rest }) => {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (open) {
ref.current?.showPopover?.();
} else {
ref.current?.hidePopover?.();
}
}, [open, ref]);
return (
<div
{...rest}
ref={ref}
// @ts-expect-error React types complain but the property works
popover="manual"
>
{children}
</div>
);
};
The way to use it is now super simple
const useOverlayState = () => {
const [open, setOpen] = useState(false);
return {
isOpen: open,
open: () => setOpen(true),
close: () => setOpen(false),
toggle: () => setOpen((o) => !o),
};
};
export default function App() {
const { isOpen, toggle } = useOverlayState();
return (
<div className="App">
<div id="bad-element"></div>
<h1>Overlay with popover attribute example</h1>
<button onClick={toggle}>
{isOpen ? `Close overlay` : `Open overlay`}
</button>
<Overlay className="overlay-popover" open={isOpen}>
I'm an overlay using popover
</Overlay>
</div>
);
}
Here is a working example of this super simple component
Since the Overlay
is moved by the browser to the top-layer this solution does not suffer from any of the issues mentioned in the question.
This Popover can be used as a foundation for other more complex/useful components like
PositionableOverlay
(fortooltips
andpopovers
)Modals
(The Dialog element might also be useful for this one)SlidingPanels
Basically anything that need to behave like an overlay
.
本文标签:
版权声明:本文标题:javascript - Implement a React Popover primitive that is not affected by other layers z-index values or position fixed issues in 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744264006a2597858.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论