fix(use-aria-overlay): prevent modal/drawer from closing on press instead (#5624)

* fix(modal/drawer): prevent modal/drawer from closing on press instead

* refactor(useAriaOverlay): improve getOverlayTypeFromRef with ARIA checks and hoist

* refactor(useAriaOverlay): add alertdialog & fallback to modal when aria-modal is missing

* Merge branch 'canary' into pr/5624

* chore(changeset): add issue number

* refactor(use-aria-overlay): getOverlayInteractionType

---------

Co-authored-by: WK Wong <wingkwong.code@gmail.com>
This commit is contained in:
Anshuman Singh Rathore 2025-08-30 19:22:32 +05:30 committed by GitHub
parent e0dc33f3b6
commit b6fda4fe6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 1 deletions

View File

@ -0,0 +1,5 @@
---
"@heroui/use-aria-overlay": patch
---
prevent modal/drawer from closing on press instead (#5616)

View File

@ -65,7 +65,9 @@ export function useAriaOverlay(props: UseAriaOverlayProps, ref: RefObject<Elemen
e.preventDefault();
}
}
onHide();
if (getOverlayInteractionType(ref) !== "pressEnd") {
onHide();
}
}
};
@ -130,6 +132,38 @@ export function useAriaOverlay(props: UseAriaOverlayProps, ref: RefObject<Elemen
}
};
/**
* Determines the interaction type for overlay dismissal based on the element's ARIA role.
* @param ref - Reference to the overlay element
* @returns "pressEnd" for dialogs (close on release), "pressStart" for menus (close on press), or "unknown"
*/
function getOverlayInteractionType(
ref: RefObject<Element>,
): "pressEnd" | "pressStart" | "unknown" {
const el = ref.current;
if (!el) return "unknown";
const role = (el.getAttribute("role") || "").toLowerCase();
const ariaModalAttr = el.getAttribute("aria-modal");
// Dialogs (Modal/Drawer) should close on press release.
// Include alertdialog and treat missing aria-modal (unless explicitly "false") as modal.
if (
(role === "dialog" || role === "alertdialog") &&
(ariaModalAttr === null || ariaModalAttr.toLowerCase() === "true")
) {
return "pressEnd";
}
// Select-like/menu-like overlays typically close on press start.
if (["listbox", "menu", "tree", "grid", "combobox"].includes(role)) {
return "pressStart";
}
return "unknown";
}
return {
overlayProps: {
onKeyDown,