From b49ab1a9f4aa6eb64a95452f268e6c694d14d667 Mon Sep 17 00:00:00 2001 From: Ebrahim Bangdiwala Date: Sat, 13 Dec 2025 00:56:09 +0530 Subject: [PATCH 1/2] fix: hide modal close button when not dismissible The close button in the modal header now only renders when the modal is dismissible. This prevents confusion where users see a close button but the modal cannot be dismissed by clicking outside or pressing Escape. Changes: - Add dismissible prop to ModalContext - Conditionally render close button in ModalHeader based on dismissible - Add tests to verify close button visibility behavior --- .../ui/src/components/Modal/Modal.test.tsx | 30 ++++++++++++++++++- packages/ui/src/components/Modal/Modal.tsx | 1 + .../ui/src/components/Modal/ModalContext.tsx | 1 + .../ui/src/components/Modal/ModalHeader.tsx | 9 ++++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/components/Modal/Modal.test.tsx b/packages/ui/src/components/Modal/Modal.test.tsx index fcfde70bf8..aa522c9b74 100644 --- a/packages/ui/src/components/Modal/Modal.test.tsx +++ b/packages/ui/src/components/Modal/Modal.test.tsx @@ -26,6 +26,34 @@ describe("Components / Modal", () => { expect(modal).not.toBeInTheDocument(); }); + it("should not render close button when modal is not dismissible", async () => { + const user = userEvent.setup(); + + render(); + + await user.click(triggerButton()); + + const modal = dialog(); + expect(modal).toBeInTheDocument(); + + const closeButton = screen.queryByLabelText("Close"); + expect(closeButton).not.toBeInTheDocument(); + }); + + it("should render close button when modal is dismissible", async () => { + const user = userEvent.setup(); + + render(); + + await user.click(triggerButton()); + + const modal = dialog(); + expect(modal).toBeInTheDocument(); + + const closeButton = screen.queryByLabelText("Close"); + expect(closeButton).toBeInTheDocument(); + }); + it("should append to root element when root prop is provided", async () => { const root = document.createElement("div"); const user = userEvent.setup(); @@ -82,7 +110,7 @@ describe("Components / Modal", () => { it("should close `Modal` when `Space` is pressed on any of its buttons", async () => { const user = userEvent.setup(); - render(); + render(); const openButton = triggerButton(); diff --git a/packages/ui/src/components/Modal/Modal.tsx b/packages/ui/src/components/Modal/Modal.tsx index 18c0252d90..be383283c5 100644 --- a/packages/ui/src/components/Modal/Modal.tsx +++ b/packages/ui/src/components/Modal/Modal.tsx @@ -117,6 +117,7 @@ export const Modal = forwardRef((props, ref) => { clearTheme: props.clearTheme, applyTheme: props.applyTheme, popup, + dismissible, onClose, setHeaderId, }} diff --git a/packages/ui/src/components/Modal/ModalContext.tsx b/packages/ui/src/components/Modal/ModalContext.tsx index 8476bbfbe1..67a4e844a4 100644 --- a/packages/ui/src/components/Modal/ModalContext.tsx +++ b/packages/ui/src/components/Modal/ModalContext.tsx @@ -6,6 +6,7 @@ import type { ModalTheme } from "./Modal"; export interface ModalContextValue extends ThemingProps { popup?: boolean; + dismissible?: boolean; setHeaderId: (id: string | undefined) => void; onClose?: () => void; } diff --git a/packages/ui/src/components/Modal/ModalHeader.tsx b/packages/ui/src/components/Modal/ModalHeader.tsx index db2291c027..fc15f03065 100644 --- a/packages/ui/src/components/Modal/ModalHeader.tsx +++ b/packages/ui/src/components/Modal/ModalHeader.tsx @@ -31,6 +31,7 @@ export const ModalHeader = forwardRef((props, clearTheme: rootClearTheme, applyTheme: rootApplyTheme, popup, + dismissible, onClose, setHeaderId, } = useModalContext(); @@ -64,9 +65,11 @@ export const ModalHeader = forwardRef((props, {children} - + {dismissible && ( + + )} ); }); From e8d03b00fc6666ef91f6c78ff185d92b566227fb Mon Sep 17 00:00:00 2001 From: Ebrahim Bangdiwala Date: Mon, 15 Dec 2025 16:08:09 +0530 Subject: [PATCH 2/2] Add changeset --- .changeset/social-kings-cut.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/social-kings-cut.md diff --git a/.changeset/social-kings-cut.md b/.changeset/social-kings-cut.md new file mode 100644 index 0000000000..8d2b277beb --- /dev/null +++ b/.changeset/social-kings-cut.md @@ -0,0 +1,5 @@ +--- +"flowbite-react": patch +--- + +Ensure modal close button respects dismissible prop