✨(react) add closeOnEsc props to Modal
We want to be able to disable closing modals by pressing escape in some cases.
This commit is contained in:
@@ -149,6 +149,12 @@ You can change this behavior by passing the `closeOnClickOutside` prop.
|
|||||||
|
|
||||||
<Canvas of={Stories.CloseOnClickOutside} story={{inline: false}}/>
|
<Canvas of={Stories.CloseOnClickOutside} story={{inline: false}}/>
|
||||||
|
|
||||||
|
## Close on escape
|
||||||
|
|
||||||
|
By default, the modal will be closed when you press the `esc` key. You can change this behavior by passing the `closeOnEsc` prop.
|
||||||
|
|
||||||
|
<Canvas of={Stories.DontCloseOnEsc} story={{inline: false}}/>
|
||||||
|
|
||||||
## Pre Built Modals
|
## Pre Built Modals
|
||||||
|
|
||||||
As we know that developers love to have handy shortcuts for common use cases, we provide some pre built modals that we
|
As we know that developers love to have handy shortcuts for common use cases, we provide some pre built modals that we
|
||||||
|
|||||||
@@ -209,6 +209,54 @@ describe("<Modal/>", () => {
|
|||||||
await user.click(modal);
|
await user.click(modal);
|
||||||
expect(screen.queryByText("Modal Content")).toBeInTheDocument();
|
expect(screen.queryByText("Modal Content")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
it("close on esc by default", async () => {
|
||||||
|
const Wrapper = () => {
|
||||||
|
const modal = useModal();
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<button onClick={modal.open}>Open Modal</button>
|
||||||
|
<Modal size={ModalSize.SMALL} {...modal}>
|
||||||
|
<div>Modal Content</div>
|
||||||
|
</Modal>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<Wrapper />);
|
||||||
|
const user = userEvent.setup();
|
||||||
|
const button = screen.getByText("Open Modal");
|
||||||
|
|
||||||
|
expect(screen.queryByText("Modal Content")).not.toBeInTheDocument();
|
||||||
|
await user.click(button);
|
||||||
|
expect(screen.getByText("Modal Content")).toBeInTheDocument();
|
||||||
|
|
||||||
|
await user.keyboard("{Escape}");
|
||||||
|
expect(screen.queryByText("Modal Content")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
it("does not close on esc when using closeOnEsc=false", async () => {
|
||||||
|
const Wrapper = () => {
|
||||||
|
const modal = useModal();
|
||||||
|
return (
|
||||||
|
<CunninghamProvider>
|
||||||
|
<button onClick={modal.open}>Open Modal</button>
|
||||||
|
<Modal size={ModalSize.SMALL} closeOnEsc={false} {...modal}>
|
||||||
|
<div>Modal Content</div>
|
||||||
|
</Modal>
|
||||||
|
</CunninghamProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<Wrapper />);
|
||||||
|
const user = userEvent.setup();
|
||||||
|
const button = screen.getByText("Open Modal");
|
||||||
|
|
||||||
|
expect(screen.queryByText("Modal Content")).not.toBeInTheDocument();
|
||||||
|
await user.click(button);
|
||||||
|
expect(screen.getByText("Modal Content")).toBeInTheDocument();
|
||||||
|
|
||||||
|
await user.keyboard("{Escape}");
|
||||||
|
expect(screen.queryByText("Modal Content")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It should also prevent the modal from closing when pressing the escape key, but it appears
|
* It should also prevent the modal from closing when pressing the escape key, but it appears
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ export const CloseOnClickOutside: Story = {
|
|||||||
closeOnClickOutside: true,
|
closeOnClickOutside: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
export const DontCloseOnEsc: Story = {
|
||||||
|
args: {
|
||||||
|
size: ModalSize.MEDIUM,
|
||||||
|
closeOnEsc: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
export const PreventClose: Story = {
|
export const PreventClose: Story = {
|
||||||
args: {
|
args: {
|
||||||
size: ModalSize.MEDIUM,
|
size: ModalSize.MEDIUM,
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export type ModalProps = PropsWithChildren & {
|
|||||||
titleIcon?: React.ReactNode;
|
titleIcon?: React.ReactNode;
|
||||||
hideCloseButton?: boolean;
|
hideCloseButton?: boolean;
|
||||||
closeOnClickOutside?: boolean;
|
closeOnClickOutside?: boolean;
|
||||||
|
closeOnEsc?: boolean;
|
||||||
preventClose?: boolean;
|
preventClose?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ export const Modal = (props: ModalProps) => {
|
|||||||
return <ModalInner {...props} />;
|
return <ModalInner {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModalInner = (props: ModalProps) => {
|
export const ModalInner = ({ closeOnEsc = true, ...props }: ModalProps) => {
|
||||||
const { modalParentSelector } = useModals();
|
const { modalParentSelector } = useModals();
|
||||||
|
|
||||||
if (!props.isOpen) {
|
if (!props.isOpen) {
|
||||||
@@ -90,6 +91,7 @@ export const ModalInner = (props: ModalProps) => {
|
|||||||
overlayClassName="c__modal__backdrop"
|
overlayClassName="c__modal__backdrop"
|
||||||
className={classNames(MODAL_CLASS, `${MODAL_CLASS}--${props.size}`)}
|
className={classNames(MODAL_CLASS, `${MODAL_CLASS}--${props.size}`)}
|
||||||
shouldCloseOnOverlayClick={!!props.closeOnClickOutside}
|
shouldCloseOnOverlayClick={!!props.closeOnClickOutside}
|
||||||
|
shouldCloseOnEsc={closeOnEsc}
|
||||||
bodyOpenClassName={classNames("c__modals--opened", NOSCROLL_CLASS)}
|
bodyOpenClassName={classNames("c__modals--opened", NOSCROLL_CLASS)}
|
||||||
>
|
>
|
||||||
{!props.hideCloseButton && !props.preventClose && (
|
{!props.hideCloseButton && !props.preventClose && (
|
||||||
|
|||||||
Reference in New Issue
Block a user