Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions src/components/ConfirmationButton/ConfirmationButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const ConfirmationButton = ({
preModalOpenHook,
...actionButtonProps
}: Props): React.JSX.Element => {
const { openPortal, closePortal, isOpen, Portal } = usePortal();
const { openPortal, closePortal, isOpen } = usePortal();

const handleCancelModal = () => {
closePortal();
Expand Down Expand Up @@ -90,22 +90,21 @@ export const ConfirmationButton = ({
return (
<>
{isOpen && (
<Portal>
<ConfirmationModal
{...confirmationModalProps}
close={handleCancelModal}
confirmButtonLabel={confirmationModalProps.confirmButtonLabel}
onConfirm={handleConfirmModal}
>
{confirmationModalProps.children}
{showShiftClickHint && (
<p className="p-text--small u-text--muted u-hide--small">
Next time, you can skip this confirmation by holding{" "}
<code>SHIFT</code> and clicking the action.
</p>
)}
</ConfirmationModal>
</Portal>
<ConfirmationModal
{...confirmationModalProps}
close={handleCancelModal}
confirmButtonLabel={confirmationModalProps.confirmButtonLabel}
onConfirm={handleConfirmModal}
renderInPortal={true}
>
{confirmationModalProps.children}
{showShiftClickHint && (
<p className="p-text--small u-text--muted u-hide--small">
Next time, you can skip this confirmation by holding{" "}
<code>SHIFT</code> and clicking the action.
</p>
)}
</ConfirmationModal>
)}
<ActionButton
{...actionButtonProps}
Expand Down
31 changes: 31 additions & 0 deletions src/components/ConfirmationModal/ConfirmationModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,35 @@ describe("ConfirmationModal ", () => {
"submit",
);
});

it("renders without portal by default", () => {
const { container } = render(
<ConfirmationModal confirmButtonLabel="Proceed" onConfirm={jest.fn()}>
Test default rendering
</ConfirmationModal>,
);

const modal = container.querySelector(".p-modal");
expect(modal).toBeInTheDocument();
expect(container.contains(modal)).toBe(true);
});

it("renders inside a portal when renderInPortal is true", () => {
const { container } = render(
<ConfirmationModal
confirmButtonLabel="Proceed"
onConfirm={jest.fn()}
renderInPortal={true}
>
Test portal rendering
</ConfirmationModal>,
);

const modal = document.querySelector(".p-modal");
expect(modal).toBeInTheDocument();

expect(container.contains(modal)).toBe(false);

expect(document.body.contains(modal)).toBe(true);
});
});
12 changes: 11 additions & 1 deletion src/components/ConfirmationModal/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PropsWithSpread, ValueOf } from "types";
import Button, { ButtonAppearance, ButtonProps } from "components/Button";
import Modal, { ModalProps } from "components/Modal";
import ActionButton, { ActionButtonProps } from "components/ActionButton";
import { usePortal } from "external";

export type Props = PropsWithSpread<
{
Expand Down Expand Up @@ -47,6 +48,10 @@ export type Props = PropsWithSpread<
* Whether the confirm button should be disabled.
*/
confirmButtonDisabled?: boolean;
/**
* Whether to render the modal inside a Portal component.
*/
renderInPortal?: boolean;
},
Omit<ModalProps, "buttonRow">
>;
Expand All @@ -65,8 +70,11 @@ export const ConfirmationModal = ({
confirmButtonLoading,
confirmButtonDisabled,
confirmButtonProps,
renderInPortal = false,
...props
}: Props): React.JSX.Element => {
const { Portal } = usePortal();

const handleClick =
<A extends Function>( // eslint-disable-line @typescript-eslint/no-unsafe-function-type
action: A | null | undefined,
Expand All @@ -80,7 +88,7 @@ export const ConfirmationModal = ({
}
};

return (
const ModalElement = (
<Modal
buttonRow={
<>
Expand Down Expand Up @@ -110,6 +118,8 @@ export const ConfirmationModal = ({
{children}
</Modal>
);

return renderInPortal ? <Portal>{ModalElement}</Portal> : ModalElement;
};

export default ConfirmationModal;
Loading