From 671214aa2d36b3d2fe877a03b43d7839e6b39cc9 Mon Sep 17 00:00:00 2001 From: William Collins Date: Mon, 8 Dec 2025 13:47:56 -0500 Subject: [PATCH 1/2] allow passing focus options to focus trap --- src/Modal.tsx | 11 +++++++++++ src/useFocusTrap.tsx | 12 +++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Modal.tsx b/src/Modal.tsx index 4c357ae..24af12c 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -172,6 +172,15 @@ export interface BaseModalProps extends TransitionCallbacks { */ enforceFocus?: boolean; + /** + * Options passed to focus function when `enforceFocus` is set to `true` + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters + */ + enforceFocusOptions?: { + preventScroll: boolean; + }; + /** * When `true` The modal will restore focus to previously focused element once * modal is hidden @@ -272,6 +281,7 @@ const Modal: React.ForwardRefExoticComponent< autoFocus = true, enforceFocus = true, + enforceFocusOptions, restoreFocus = true, restoreFocusOptions, mountDialogOnEnter = true, @@ -307,6 +317,7 @@ const Modal: React.ForwardRefExoticComponent< const focusTrap = useFocusTrap({ getContainer: () => modal.dialog, disabled: () => !enforceFocus || !modal.isTopModal(), + enforceFocusOptions, }); useImperativeHandle(ref, () => modal, [modal]); diff --git a/src/useFocusTrap.tsx b/src/useFocusTrap.tsx index 882d8e6..93075c1 100644 --- a/src/useFocusTrap.tsx +++ b/src/useFocusTrap.tsx @@ -9,9 +9,19 @@ import activeElement from 'dom-helpers/activeElement'; export function useFocusTrap({ getContainer, disabled, + enforceFocusOptions, }: { getContainer: () => HTMLElement | null; disabled?: () => boolean; + + /** + * Options passed to focus function when trap container regains focus + * + * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters + */ + enforceFocusOptions?: { + preventScroll: boolean; + }; }) { const ownerWindow = useWindow(); const isMounted = useMounted(); @@ -60,7 +70,7 @@ export function useFocusTrap({ ) { const tabbables = getTabbableElementsOrSelf(container); - tabbables[0]?.focus(); + tabbables[0]?.focus(enforceFocusOptions); } }); From f5b2939574dba42c5585bc1aede18def400f7b55 Mon Sep 17 00:00:00 2001 From: William Collins Date: Mon, 8 Dec 2025 14:22:35 -0500 Subject: [PATCH 2/2] default to not scrolling when restoring focus in focus trap --- src/Modal.tsx | 11 ----------- src/useFocusTrap.tsx | 12 +----------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/Modal.tsx b/src/Modal.tsx index 24af12c..4c357ae 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -172,15 +172,6 @@ export interface BaseModalProps extends TransitionCallbacks { */ enforceFocus?: boolean; - /** - * Options passed to focus function when `enforceFocus` is set to `true` - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters - */ - enforceFocusOptions?: { - preventScroll: boolean; - }; - /** * When `true` The modal will restore focus to previously focused element once * modal is hidden @@ -281,7 +272,6 @@ const Modal: React.ForwardRefExoticComponent< autoFocus = true, enforceFocus = true, - enforceFocusOptions, restoreFocus = true, restoreFocusOptions, mountDialogOnEnter = true, @@ -317,7 +307,6 @@ const Modal: React.ForwardRefExoticComponent< const focusTrap = useFocusTrap({ getContainer: () => modal.dialog, disabled: () => !enforceFocus || !modal.isTopModal(), - enforceFocusOptions, }); useImperativeHandle(ref, () => modal, [modal]); diff --git a/src/useFocusTrap.tsx b/src/useFocusTrap.tsx index 93075c1..ba5a622 100644 --- a/src/useFocusTrap.tsx +++ b/src/useFocusTrap.tsx @@ -9,19 +9,9 @@ import activeElement from 'dom-helpers/activeElement'; export function useFocusTrap({ getContainer, disabled, - enforceFocusOptions, }: { getContainer: () => HTMLElement | null; disabled?: () => boolean; - - /** - * Options passed to focus function when trap container regains focus - * - * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters - */ - enforceFocusOptions?: { - preventScroll: boolean; - }; }) { const ownerWindow = useWindow(); const isMounted = useMounted(); @@ -70,7 +60,7 @@ export function useFocusTrap({ ) { const tabbables = getTabbableElementsOrSelf(container); - tabbables[0]?.focus(enforceFocusOptions); + tabbables[0]?.focus({ preventScroll: true }); } });