-
Notifications
You must be signed in to change notification settings - Fork 832
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: Allow bypassing focus lock for some elements #1859
Comments
Hey @brandon-pereira, Are you able to provide a sandbox demonstrating your issue so we can use this as a baseline? |
@brandon-pereira I'm having same issue, this is because when you use dialog, it sets style = "pointer-events: none;" to body element. this does fix it but It removes backdrop and I need the backdrop while showing radix ui dialog. I have used modal={false} and it allows me to select place but dialog close suddenly when I select place over google autocomplete dropdown. @benoitgrelard I think it should be improved but couldn't able to provide sandbox. same issue is appear on this sandbox but with mui + radix ui dialog. If you click on Movie dropdown and select 'chocolate' dialog is just disappear. |
@nimeshvaghasiya thanks for setting up the code sandbox, I didn't have the time to set one up. The reason it closes is because they are adding a focus guard to the dialog, but don't expose the controls to add external elements to ignore. |
Same problem here too, modal=false removes backdrop but would be nice to still have backdrop. |
What do you think is the best possible solution right now to get it working? We can probably add a custom backdrop ourselves. |
The |
Doesn't work in my case. I think my usecase is different. I can still use the keyboard but clicking is still necessary. How can we make it work with that? Right now I set |
something like that should add your backdrop back when modal=false |
@tarmooo Yeah adding a sheet might
Still it does not solve the problem. The main issue I think is about the focus guard/focus lock that is on the dialog as @brandon-pereira said |
I found a temporary solution that track whether the user is typing or not by using onFocus and onBlur to prevent closing of the modal. const Modal: React.FC<Props> = ({
isOpen,
onClose,
title,
description,
children,
disable,
isModal = true,
}) => {
const handleClose = () => {
if (!disable) {
onClose();
}
};
return (
<>
{isOpen && !isModal && (
<div className="fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" />
)}
<Dialog open={isOpen} onOpenChange={handleClose} modal={isModal}>
<DialogContent>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<div>{children}</div>
</DialogContent>
</Dialog>
</>
);
}; |
For anyone who's using react-google-autocomplete + radix dialog here was my solution: Add this to the Content component: onInteractOutside={(e) => {
const classes: Array<Array<string>> = [];
e.composedPath().forEach((el: any) => {
if (el.classList) {
classes.push(Array.from(el.classList));
}
});
// pac = classes naming for https://www.npmjs.com/package/react-google-autocomplete
// primary use case is the "AddContact" modal
if (classes.join("-").includes("pac-container")) {
e.preventDefault();
}
}} And anywhere you're rending the autocomplete input, just add this: useEffect(() => {
// Disable Radix ui dialog pointer events lockout
setTimeout(() => (document.body.style.pointerEvents = ""), 0)
}) |
Worked like a charm |
Had a similar problem with a flatpicker calendar, I had to add a pointers events auto class to the calendar, and create a ref for the overlay element onInteractOutside={(e) => {
if (e.target !== overlayRef.current) {
// avoid closing while interacting with timepicker calendar
e.preventDefault();
}
}} |
@BenLebich's solution also works great if your using the Google's SDK directly. I made some minor modifications - but the results are the same. onInteractOutside={(e) => {
const hasPacContainer = e.composedPath().some((el: EventTarget) => {
if ("classList" in el) {
return Array.from((el as Element).classList).includes("pac-container")
}
return false
})
if (hasPacContainer) {
e.preventDefault()
}
}} |
I have been racking my brain all day over this issue till I stumbled on this solution, works like a charm. Nice work, guys. |
I had the same problem here is how i fixed it
|
Ugh, took me a long time to track down and fix this bug. This is what worked for me (similar to the solutions above, but without the need for
There really needs to be a proper fix for this. |
My use-case was to enable animation so I needed to forceMount the Dialog, but it kept stealing the focus on re-render from other inputs I was able to fix this by doing the following:
|
Feature request
I am trying to use the Dialog component, however I noticed a bug where I am loading Google Maps Place Autocomplete service, and I'm unable to select places because they are rendered in a portal outside the dialog.
This issue also appears to exist if you use a third party
<select>
library instead of Radix. The reason this is the case for me is because I was attempting to migrate from Reach UI incrementally (modals first, then dropdowns, etc).Overview
To solve this, I think the
dialog
component should select ashards
orwhitelist
prop much like React Focus Lock to allow including external elements in the focus lock logic.Examples in other libraries
https://www.npmjs.com/package/react-focus-lock
Who does this impact? Who is this for?
Probably more advanced use cases, or anyone dealing with third party libraries or dependencies.
Additional context
None
The text was updated successfully, but these errors were encountered: