Skip to content

Commit

Permalink
fix: Fix nested Dialog not rendering correctly when the parent has …
Browse files Browse the repository at this point in the history
…a backdrop
  • Loading branch information
diegohaz committed Apr 13, 2020
1 parent 16f843f commit ce766d5
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 7 deletions.
5 changes: 3 additions & 2 deletions packages/reakit/src/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const useDialog = createHook<DialogOptions, DialogHTMLProps>({
) {
const dialog = React.useRef<HTMLElement>(null);
const backdrop = React.useContext(DialogBackdropContext);
const hasBackdrop = backdrop && backdrop === options.baseId;
const disclosures = useDisclosuresRef(dialog, options);
const onKeyDownRef = useLiveRef(htmlOnKeyDown);
const { dialogs, visibleModals, wrap } = useNestedDialogs(dialog, options);
Expand Down Expand Up @@ -174,15 +175,15 @@ export const useDialog = createHook<DialogOptions, DialogHTMLProps>({
const wrapElement = React.useCallback(
(element: React.ReactNode) => {
element = wrap(element);
if (options.modal && !backdrop) {
if (options.modal && !hasBackdrop) {
element = <Portal>{element}</Portal>;
}
if (htmlWrapElement) {
return htmlWrapElement(element);
}
return element;
},
[wrap, options.modal, backdrop, htmlWrapElement]
[wrap, options.modal, hasBackdrop, htmlWrapElement]
);

return {
Expand Down
2 changes: 1 addition & 1 deletion packages/reakit/src/Dialog/DialogBackdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const useDialogBackdrop = createHook<
if (options.modal) {
element = (
<Portal>
<DialogBackdropContext.Provider value>
<DialogBackdropContext.Provider value={options.baseId}>
{element}
</DialogBackdropContext.Provider>
</Portal>
Expand Down
104 changes: 103 additions & 1 deletion packages/reakit/src/Dialog/__tests__/index-test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react";
import { render, fireEvent, click, focus, press } from "reakit-test-utils";
import { Dialog, DialogDisclosure, useDialogState } from "..";
import { Dialog, DialogDisclosure, DialogBackdrop, useDialogState } from "..";

test("clicking on disclosure opens the dialog", () => {
const Test = () => {
Expand Down Expand Up @@ -1300,3 +1300,105 @@ test("opening a nested orphan dialog closes the parent dialog", () => {
expect(dialog2).toBeVisible();
expect(dialog2).toHaveFocus();
});

test("nested modal dialog with backdrop markup", () => {
const Test = () => {
const dialog = useDialogState({ baseId: "dialog1" });
const dialog2 = useDialogState({ baseId: "dialog2" });
return (
<>
<DialogDisclosure {...dialog}>disclosure1</DialogDisclosure>
<DialogBackdrop {...dialog}>
<Dialog {...dialog} aria-label="dialog1">
<DialogDisclosure {...dialog2}>disclosure2</DialogDisclosure>
<Dialog {...dialog2} tabIndex={0} aria-label="dialog2" />
</Dialog>
</DialogBackdrop>
</>
);
};
const { getByText, baseElement } = render(<Test />);
const disclosure1 = getByText("disclosure1");
const disclosure2 = getByText("disclosure2");
click(disclosure1);
click(disclosure2);
expect(baseElement).toMatchInlineSnapshot(`
<body
style="padding-right: 1024px; overflow: hidden;"
>
<div>
<button
aria-controls="dialog1"
aria-expanded="true"
aria-haspopup="dialog"
type="button"
>
disclosure1
</button>
</div>
<div
aria-hidden="true"
class="__reakit-focus-trap"
style="position: fixed;"
tabindex="0"
/>
<div
class="__reakit-portal"
>
<div
data-dialog-ref="dialog1"
style=""
>
<div
aria-label="dialog1"
data-dialog="true"
id="dialog1"
role="dialog"
style=""
tabindex="-1"
>
<button
aria-controls="dialog2"
aria-expanded="true"
aria-haspopup="dialog"
type="button"
>
disclosure2
</button>
</div>
</div>
<div
aria-hidden="true"
class="__reakit-focus-trap"
style="position: fixed;"
tabindex="0"
/>
<div
class="__reakit-portal"
>
<div
aria-label="dialog2"
aria-modal="true"
data-dialog="true"
id="dialog2"
role="dialog"
style=""
tabindex="0"
/>
</div>
<div
aria-hidden="true"
class="__reakit-focus-trap"
style="position: fixed;"
tabindex="0"
/>
</div>
<div
aria-hidden="true"
class="__reakit-focus-trap"
style="position: fixed;"
tabindex="0"
/>
</body>
`);
});
4 changes: 3 additions & 1 deletion packages/reakit/src/Dialog/__utils/DialogBackdropContext.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as React from "react";

export const DialogBackdropContext = React.createContext(false);
export const DialogBackdropContext = React.createContext<string | undefined>(
undefined
);
4 changes: 2 additions & 2 deletions packages/reakit/src/Disclosure/DisclosureContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const useDisclosureContent = createHook<

React.useEffect(() => {
if (!options.animated) return undefined;
const raf = requestAnimationFrame(() => {
const raf = window.requestAnimationFrame(() => {
if (options.visible) {
setTransition("enter");
} else if (animating) {
Expand All @@ -54,7 +54,7 @@ export const useDisclosureContent = createHook<
setTransition(null);
}
});
return () => cancelAnimationFrame(raf);
return () => window.cancelAnimationFrame(raf);
}, [options.animated, options.visible, animating]);

const onEnd = React.useCallback(
Expand Down

0 comments on commit ce766d5

Please sign in to comment.