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
2 changes: 1 addition & 1 deletion apps/web/content/docs/components/modal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Use the `<Modal>` React component to show a dialog element to the user with a he

The visibility of the component can be set by passing a boolean value to the `show` prop on the `<Modal>` component and we recommend you to do this via the React state.

Using a `openModal` and `setOpenModal` state for the main React component should allow you to easily manage the state of the Modal component and use inline functions on event listeners such as `onClick` or `onClose`.
Using a `openModal` and `setOpenModal` state for the main React component should allow you to easily manage the state of the Modal component and use inline functions on event listeners such as `onClick` or `onClose`. When you pass the `onClose` prop, the header close (X) button is shown and calls `onClose` when clicked.

<Example name="modal.root" />

Expand Down
44 changes: 38 additions & 6 deletions packages/ui/src/components/Modal/Modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,23 @@ describe("Components / Modal", () => {
expect(modal).not.toBeInTheDocument();
});

it("should not render close button when modal is not dismissible", async () => {
it("should not close on backdrop press when dismissible but onClose is not provided", async () => {
const user = userEvent.setup();

render(<TestModal />);
render(<TestModalWithoutOnClose dismissible />);

await user.click(triggerButton());
const modal = dialog();
expect(modal).toBeInTheDocument();

await user.click(dialogOverlay());
expect(modal).toBeInTheDocument();
});

it("should not render close button when onClose is not provided", async () => {
const user = userEvent.setup();

render(<TestModalWithoutOnClose />);

await user.click(triggerButton());

Expand All @@ -40,10 +53,10 @@ describe("Components / Modal", () => {
expect(closeButton).not.toBeInTheDocument();
});

it("should render close button when modal is dismissible", async () => {
it("should render close button when onClose is provided", async () => {
const user = userEvent.setup();

render(<TestModal dismissible />);
render(<TestModal />);

await user.click(triggerButton());

Expand Down Expand Up @@ -110,7 +123,7 @@ describe("Components / Modal", () => {
it("should close `Modal` when `Space` is pressed on any of its buttons", async () => {
const user = userEvent.setup();

render(<TestModal dismissible />);
render(<TestModal />);

const openButton = triggerButton();

Expand Down Expand Up @@ -145,7 +158,7 @@ describe("Components / Modal", () => {
const user = userEvent.setup();
const inputRef = createRef<HTMLInputElement>();

render(<TestModal dismissible inputRef={inputRef} />);
render(<TestModal inputRef={inputRef} />);

await user.click(triggerButton());
const modal = dialog();
Expand Down Expand Up @@ -219,6 +232,25 @@ const TestModal = ({
);
};

const TestModalWithoutOnClose = ({
root,
dismissible = false,
}: Pick<ModalProps, "root" | "dismissible">): JSX.Element => {
const [open, setOpen] = useState(false);

return (
<>
<Button onClick={() => setOpen(true)}>Toggle modal</Button>
<Modal root={root} show={open} dismissible={dismissible}>
<ModalHeader id="test-dialog-header">Terms of Service</ModalHeader>
<ModalBody>
<p className="text-base leading-relaxed text-gray-500 dark:text-gray-400">Modal without onClose</p>
</ModalBody>
</Modal>
</>
);
};

const dialog = () => screen.getByRole("dialog");
const dialogOverlay = () => screen.getByTestId("modal-overlay");
const triggerButton = () => screen.getByRole("button", { name: "Toggle modal" });
Expand Down
3 changes: 1 addition & 2 deletions packages/ui/src/components/Modal/ModalHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>((props,
clearTheme: rootClearTheme,
applyTheme: rootApplyTheme,
popup,
dismissible,
onClose,
setHeaderId,
} = useModalContext();
Expand Down Expand Up @@ -65,7 +64,7 @@ export const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>((props,
<Component id={headerId} className={theme.title}>
{children}
</Component>
{dismissible && (
{onClose != null && (
<button aria-label="Close" className={theme.close.base} type="button" onClick={onClose}>
<OutlineXIcon aria-hidden className={theme.close.icon} />
</button>
Expand Down
Loading