-
Notifications
You must be signed in to change notification settings - Fork 733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Dialog][Popover] Scrolling issue when Popover inside Dialog #1159
Comments
Both compositions are valid, for different use cases. |
It's not overlay that I need scrollable though. I'll come up with a code sandbox to show what I'm talking about |
Here you can see if you follow all of the docs for both popover and dialog you can't scroll a popover in a dialog. I had to read through radix's source code and dependencies to figure out that I needed to wrap my content in the overlay. While both are valid I think the docs should steer people towards code+structure that will work out of the box without having to understand how the internals are actually working. |
And if you're unwilling to change that I think the docs should at least detail why both composition are valid and what the use cases actually are. |
Oh sorry I misunderstood what you meant! |
Hmm, yep looks like it could be a |
…dal content into overlay children
I'm running into the same issue. I'd like to adopt Radix for the design system I'm working on but we have some custom selects with a scrollable area (implemented as popover) which are rendered inside modals. Would it be possible to disable the scroll-blocking in the dialog components? Or just to enable scroll-blocking of the body since the rest is not scrollable because of the dialog overlay anyway. |
To anyone reading, I just found a workaround. The scroll removal is implemented in the primitives/packages/react/dialog/src/Dialog.tsx Lines 201 to 219 in 6da75e0
So replacing the |
Thanks @hipstersmoothie @dcastil ! |
Ran into this as well, when using non-Radix UI bits inside a Dialog. Would really be nice to have an option to disable it. |
Any news on this? scroll doesn't work on third parties with Radix dialog. |
Yeah, this is still an issue for us |
This was the best solution for me for now as it doesn't remove the overlay. It also fixed an issue where padding was getting added to the body of my application whenever the overlay was showing. Thanks @dcastil |
Possible SolutionI think it's possible to use the reference of a wrapper or another one that is inside the modal based on this: Radixconst ExampleOfAnyPopoverInsideModal = () => {
const containerRef = useRef<HTMLDivElement>(null);
return (
<div ref={containerRef}>
<Popover.Root>
<Popover.Trigger />
<Popover.Anchor />
<Popover.Portal>
<Popover.Content container={containerRef.current}>
<Popover.Close />
<Popover.Arrow />
</Popover.Content>
</Popover.Portal>
</Popover.Root>
</div>
);
}; Shadcn:const ExampleOfAnyPopoverInsideModal = () => {
const containerRef = useRef<HTMLDivElement>(null);
const [open, setOpen] = useState(false);
return (
<div ref={containerRef}>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="w-full justify-between"
>
<span className="truncate">Something</span>
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent
className="p-0"
style={{
width: containerRef.current?.offsetWidth
}}
container={containerRef.current}
>
<Command>
//Command with scroll inside :)
</Command>
</PopoverContent>
</Popover>
</div>
);
}; // ...
// Added container prop to PopoverContent
const PopoverContent = React.forwardRef<
React.ElementRef<typeof PopoverPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> & {
container?: HTMLElement | null;
}
>(
(
{ className, container, align = "center", sideOffset = 4, ...props },
ref
) => (
<PopoverPrimitive.Portal container={container}>
<PopoverPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
"z-50 w-72 rounded-lg border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
</PopoverPrimitive.Portal>
)
);
// ... |
A handy tip to anyone implementing the solution from @illodev - if this will seem like devs have to pass the |
This helped me a lot! @illodev |
I think solution suggested by @illodev defeats the purpose of portal, it's really no different than just removing the portal, and that's easier. |
@ozguruysal that's correct. |
The solution by @illodev also does not work if your |
Worth mentioning that this also happens to other components that renders in portal. i.e When rendering a react-select with |
@benoitgrelard Is it possible to get a review on this PR? It sounds like it would solve this issue and it's been open for quite a while now so it would be good to get it merged. Thanks! |
also just ran into this as well! |
facing this issue.. any other workarounds, other than removing portal from popover and DialogPrimitive.Overlay ? I would like to keep those. |
ILY <3 |
Facing the same issue. |
Same thing here... @illodev doesn't entirely solve the issue: See the popover content being cut off by the modal's boundaries. So I either lose scroll or get the popover completely cut off. EDIT: This is answer is what ultimately did the trick for me: I'm a shadcn user, so I basically replaced the Screen.Recording.2024-05-23.at.3.15.49.PM.mov |
You can try avoid event propagation on popover. Use NextUI select as an example: <Select
popoverProps={{
onWheel: (e) => {
e.stopPropagation()
}
}}
>
{topics.map((item) => (
<SelectItem key={item.value} value={item.value} aria-label={item.label}>
{item.label}
</SelectItem>
))}
</Select> |
This one actually solved my issue without removing overlay or setting |
Hi, illodev. |
@illodev |
@DophinL the best solution! I also added the same to |
I've tried all of the solutions and none of them have worked entirely for me, as I'm experiencing a flickering when hovering over a popover trigger with an SVG icon. I tried all the solutions and nothing exactly works. Wondering if anyone else has any other solutions for this. |
Could you maybe add a prop on Overlay component, making the Setting modal={false} just removes the overlay I think. |
THANK YOU SO MUCH. I WAS MESSING WITH THIS FOREVER!!! |
Documentation
Relevant Radix Component(s)
Here in the docs it say to make
Overlay
a sibling toContent
.This setup doesn't work if you have a scrollable popover in the dialog content. On this line a ref is passed to
RemoveScroll
but I think that by using just a ref thatRemoveScroll
doesn't consider the portalled element a part of the react tree.In my own code I fixed this by putting my
Content
inside of myOverlay
. After this change my scrollable popover could scroll again sinceRemoveScroll
now has access to the react tree.The text was updated successfully, but these errors were encountered: