Skip to content

Commit 9d7dae8

Browse files
committed
component: focus trap to ignore nested traps
1 parent 4049518 commit 9d7dae8

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

packages/component/src/Transcript/FocusTrap.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ const FocusTrap = ({
2828
const onFocusRef = useRefFrom(onFocus);
2929
const onLeaveRef = useRefFrom(onLeave);
3030

31-
const getTabbableElementsInBody = useCallback(
32-
() => tabbableElements(bodyRef.current).filter(element => element.getAttribute('aria-disabled') !== 'true'),
33-
[bodyRef]
34-
);
31+
const getTabbableElementsInBody = useCallback(() => {
32+
const nestedTraps = Array.from(bodyRef.current?.querySelectorAll('.webchat__focus-trap'));
33+
return tabbableElements(bodyRef.current)
34+
.filter(element => element.getAttribute('aria-disabled') !== 'true')
35+
.filter(element => !nestedTraps.some(trap => trap.contains(element)));
36+
}, [bodyRef]);
3537

3638
const focusOrTriggerLeave = useCallback(
3739
(element: HTMLElement | undefined) => (element ? element.focus() : onLeaveRef.current?.()),
@@ -85,6 +87,8 @@ const FocusTrap = ({
8587
event.stopPropagation();
8688

8789
focusOrTriggerLeave(focusables.at(0));
90+
} else if (bodyRef.current.contains(target)) {
91+
event.stopPropagation();
8892
}
8993
},
9094
[focusOrTriggerLeave, getTabbableElementsInBody]
@@ -109,7 +113,13 @@ const FocusTrap = ({
109113

110114
return (
111115
<Fragment>
112-
<div onBlur={handleBlur} onFocus={handleFocus} onKeyDown={handleBodyKeyDown} ref={bodyRef}>
116+
<div
117+
className="webchat__focus-trap"
118+
onBlur={handleBlur}
119+
onFocus={handleFocus}
120+
onKeyDown={handleBodyKeyDown}
121+
ref={bodyRef}
122+
>
113123
{children}
114124
</div>
115125
<div aria-hidden="true" className={targetClassName} onFocus={handleTrapFocus} tabIndex={-1} />

0 commit comments

Comments
 (0)