Skip to content
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 V2 does not work when stacked over Overlays or other components using useOnClickOutside #2857

Open
iansan5653 opened this issue Feb 3, 2023 · 7 comments

Comments

@iansan5653
Copy link
Contributor

Description

The new draft Dialog component does not use useOnClickOutside under the hood, because it has its own backdrop element that it could handle clicks on if necessary. This makes sense, but unfortunately breaks the dialog when stacked over Overlay, AnchoredOverlay, or similar.

This is because when a component under the dialog has registered a click-outside handler using useOnClickOutside, a click in the Dialog is seen as a click outside of the overlay.

useOnClickOutside automatically handles this for stacked overlays by maintaining a global registry, but because Dialog does not call useOnClickOutside, it does not get registered to that global registry.

The workaround here is non-obvious but simple: call useOnClickOutside inside Dialog, even though the handler will be a no-op. The containerRef passed to useOnClickOutside must include the backdrop element so that there are never any clicks outside registered. This will cause all clicks to be registered as inside the Dialog, stopping them from propagating.

const backdropRef = useRef(null)

useOnClickOutside({containerRef: backdropRef, onClickOutside: () => { /* no-op */ }})

Steps to reproduce

I couldn't get CodeSandbox working with the latest version of Primer, so here's a full demo as code instead:

import { Button, Overlay, OverlayProps } from "@primer/react";
import { Dialog } from "@primer/react/drafts";
import { useState, useRef } from "react";

const OverlayWithDialog = (props: OverlayProps) => {
  const [dialogVisible, setDialogVisible] = useState(false);

  return (
    <>
      <Overlay {...props}>
        <Button onClick={() => setDialogVisible(true)}>Open Dialog</Button>
      </Overlay>

      {dialogVisible && (
        <Dialog onClose={() => setDialogVisible(false)}>
          Clicking inside me should not close me or the overlay, but it does.
        </Dialog>
      )}
    </>
  );
};

export default function App() {
  const [overlayVisible, setOverlayVisible] = useState(false);
  const buttonRef = useRef<HTMLButtonElement>(null);

  return (
    <>
      <Button onClick={() => setOverlayVisible(true)} ref={buttonRef}>
        Open Overlay
      </Button>
      {overlayVisible && (
        <OverlayWithDialog
          returnFocusRef={buttonRef}
          onClickOutside={() => setOverlayVisible(false)}
          onEscape={() => setOverlayVisible(false)}
        />
      )}
    </>
  );
}

Version

v35.19.0

Browser

Chrome

@iansan5653 iansan5653 added the bug Something isn't working label Feb 3, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Oct 8, 2023

Hi! This issue has been marked as stale because it has been open with no activity for 180 days. You can comment on the issue or remove the stale label to keep it open. If you do nothing, this issue will be closed in 7 days.

@github-actions github-actions bot added the Stale label Oct 8, 2023
@iansan5653 iansan5653 removed the Stale label Oct 9, 2023
Copy link
Contributor

github-actions bot commented Apr 6, 2024

Hi! This issue has been marked as stale because it has been open with no activity for 180 days. You can comment on the issue or remove the stale label to keep it open. If you do nothing, this issue will be closed in 7 days.

@github-actions github-actions bot added the Stale label Apr 6, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 13, 2024
@iansan5653
Copy link
Contributor Author

🙃

@iansan5653 iansan5653 reopened this Apr 16, 2024
@iansan5653 iansan5653 removed the Stale label Apr 16, 2024
Copy link
Contributor

Hi! This issue has been marked as stale because it has been open with no activity for 180 days. You can comment on the issue or remove the stale label to keep it open. If you do nothing, this issue will be closed in 7 days.

@github-actions github-actions bot added the Stale label Oct 13, 2024
@lesliecdubs
Copy link
Member

@keithamus is there a chance https://github.com/github/primer/issues/2531 would solve this?

@github-actions github-actions bot removed the Stale label Oct 14, 2024
@keithamus
Copy link
Member

Yes. We wouldn’t use onclickoutside but rather the native dialog functionality (which would need to be polyfilled but it’s something we can scope into that epic)

@lesliecdubs
Copy link
Member

Thanks! Adding this as a piece of "Corresponding Work" to https://github.com/github/primer/issues/2531 for future consideration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants