[bug]: Dialog leaves "pointer-events: none" on body after closing
When using dialog/alert components in the application:
Opening a dialog adds `pointer-events: none` to the <body> tag (expected behavior)
Bug: After closing the dialog, the style persists (unexpected behavior)
Impact:
Users cannot interact with the page
Page appears to hang/freeze
Requires manual refresh to restore functionality
The pointer-events: none style should be automatically removed when the dialog closes.
+1, running into the same issue when using Dialog from @radix-ui/[email protected]
Hitting the same problem here with latest version (1.1.15): <body class="..." the "pointer-events:none;" style is left on the
element after the dialog closes - curiously, it is not evident while the dialog is open. The problem only seems to occur if the Dialog does not use DialogTrigger and the open state is maintained by the application with const [open, setOpen] = useState(false) and <Dialog open={open} onOpenChange={setOpen}> (sorry, that's ShadCN markup, which uses @radix-ui/react-dialog under the covers).The bug disables all pointer interactions and necessitates a browser page refresh to restore application functionality.
After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.
My workaround was a useEffect like this:
const [open, setOpen] = useState<boolean>(false);
useEffect(() => {
if (open) return;
// The setTimeout is necessary because otherwise it might fire before the component is closed
setTimeout(() => {
document.body.style.pointerEvents = "auto";
}, 1);
}, [open])
return (
<Dialog open={open} onOpenChange={setOpen} />
)
After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.
My workaround was a useEffect like this: ...
Thanks for the response @chris-ldg. I agree with your analysis and had in fact implemented a similar workaround myself.
Possible duplicate of #3317 and #3445.
After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.
My workaround was a useEffect like this:
const [open, setOpen] = useState
(false); useEffect(() => { if (open) return; // The setTimeout is necessary because otherwise it might fire before the component is closed setTimeout(() => { document.body.style.pointerEvents = "auto"; }, 1); }, [open])
return ( <Dialog open={open} onOpenChange={setOpen} /> )
@chris-ldgk Ugly. But it does the job for now. Thank you
Hoping for a fix soon from Radix
@thebiltheory @devmahmoudi
I am using Shadcn, but the following solution should work for those too who are not using it.
Downloaded the radix-ui package:
yarn add radix-ui
And then import just the Dialog from it:
import { Dialog as DialogPrimitive } from "radix-ui";
Also, you might need to import the Alert from the radix-ui package as well. As the same issue with dialogs is present in alerts as well, since they use the same primitive (afaik).
Fixed it for me.
I experienced a similar issue with the shadcn dialog component. I "fixed" by reverting to the previous version:
npm install @radix-ui/[email protected]
Unfortunately I am still going through the same issue, no matter the version. My current workaround was cleaning up event pointers: none after closing the dialog, which is far from ideal.
A one-liner stop-gap fix (you'd need to remember to use it everywhere though) https://github.com/shadcn-ui/ui/issues/1912#issuecomment-1810037351