@@ -124,6 +175,13 @@ Modal.Header = ({ children }) => {
aria-label="Close"
className="p-2 -m-2"
onClick={onClose}
+ onKeyDown={(event) => {
+ // Product requirement: when dismissible=false, modal must close only on mouse click.
+ // Block keyboard activation on the close button (Enter/Space).
+ if (!dismissible && (event.key === "Enter" || event.key === " ")) {
+ event.preventDefault()
+ }
+ }}
>
diff --git a/packages/docs/src/stories/composite/Modal.stories.tsx b/packages/docs/src/stories/composite/Modal.stories.tsx
index b6a467873..ddeb9f8ed 100644
--- a/packages/docs/src/stories/composite/Modal.stories.tsx
+++ b/packages/docs/src/stories/composite/Modal.stories.tsx
@@ -70,6 +70,28 @@ export const Default: StoryFn = () => {
)
}
+/**
+ * Modal that can be dismissed by clicking the backdrop or pressing Esc.
+ */
+export const Dismissible: StoryFn = () => {
+ const [show, setShow] = useState(false)
+
+ const handleClose = () => setShow(false)
+ const handleShow = () => setShow(true)
+
+ return (
+
+ Open dismissible modal
+
+ Dismissible modal
+
+ This modal can be closed by clicking outside or pressing Escape.
+
+
+
+ )
+}
+
/**
* Modal with a long, scrollable content.
*/