mirror of
https://github.com/open-webui/open-webui.git
synced 2026-11-15 09:31:21 +00:00
fix(a11y): windows opened from a menu return focus to the menu button when they close (#33601)
This commit is contained in:
parent
0171427a10
commit
a671146b91
2 changed files with 38 additions and 1 deletions
|
|
@ -41,6 +41,21 @@
|
|||
let mounted = false;
|
||||
|
||||
let focusTrap: FocusTrap.FocusTrap | null = null;
|
||||
let returnFocusTarget: HTMLElement | null = null;
|
||||
|
||||
const handleFocusOutside = (event: FocusEvent) => {
|
||||
if (
|
||||
event.target instanceof HTMLElement &&
|
||||
!modalElement?.contains(event.target) &&
|
||||
!event.target.closest('[role="menu"], [role="listbox"]')
|
||||
) {
|
||||
returnFocusTarget = event.target;
|
||||
}
|
||||
};
|
||||
|
||||
const getReturnFocus = (previous: HTMLElement | SVGElement) =>
|
||||
previous.isConnected ? previous : (returnFocusTarget ?? previous);
|
||||
|
||||
let previousOverflow: string | null = null;
|
||||
const restoreOverflow = () => {
|
||||
if (previousOverflow !== null) {
|
||||
|
|
@ -93,16 +108,19 @@
|
|||
$: if (mounted) {
|
||||
if (show && modalElement) {
|
||||
document.body.appendChild(modalElement);
|
||||
focusTrap = FocusTrap.createFocusTrap(modalElement);
|
||||
returnFocusTarget = null;
|
||||
focusTrap = FocusTrap.createFocusTrap(modalElement, { setReturnFocus: getReturnFocus });
|
||||
focusTrap.activate();
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('focusin', handleFocusOutside, true);
|
||||
previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else if (modalElement) {
|
||||
focusTrap.deactivate();
|
||||
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
window.removeEventListener('focusin', handleFocusOutside, true);
|
||||
document.body.removeChild(modalElement);
|
||||
|
||||
restoreOverflow();
|
||||
|
|
@ -113,6 +131,7 @@
|
|||
show = false;
|
||||
restoreOverflow();
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
window.removeEventListener('focusin', handleFocusOutside, true);
|
||||
if (focusTrap) {
|
||||
focusTrap.deactivate();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
// https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html
|
||||
// https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html
|
||||
let focusTrap: FocusTrap.FocusTrap | null = null;
|
||||
let returnFocusTarget: HTMLElement | null = null;
|
||||
|
||||
const sizeToWidth = (size: string) => {
|
||||
if (size === 'full') {
|
||||
|
|
@ -58,6 +59,19 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleFocusOutside = (event: FocusEvent) => {
|
||||
if (
|
||||
event.target instanceof HTMLElement &&
|
||||
!modalElement?.contains(event.target) &&
|
||||
!event.target.closest('[role="menu"], [role="listbox"]')
|
||||
) {
|
||||
returnFocusTarget = event.target;
|
||||
}
|
||||
};
|
||||
|
||||
const getReturnFocus = (previous: HTMLElement | SVGElement) =>
|
||||
previous.isConnected ? previous : (returnFocusTarget ?? previous);
|
||||
|
||||
const isTopModal = () => {
|
||||
const modals = document.getElementsByClassName('modal');
|
||||
return modals.length && modals[modals.length - 1] === modalElement;
|
||||
|
|
@ -74,6 +88,7 @@
|
|||
window.removeEventListener('focusin', handleOutsideInteraction, true);
|
||||
}
|
||||
if (handleModalFocusIn) modalElement?.removeEventListener('focusin', handleModalFocusIn);
|
||||
window.removeEventListener('focusin', handleFocusOutside, true);
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
if (previousOverflow !== null) {
|
||||
document.body.style.overflow = previousOverflow;
|
||||
|
|
@ -83,8 +98,10 @@
|
|||
|
||||
$: if (show && modalElement) {
|
||||
document.body.appendChild(modalElement);
|
||||
returnFocusTarget = null;
|
||||
focusTrap = FocusTrap.createFocusTrap(modalElement, {
|
||||
escapeDeactivates: false,
|
||||
setReturnFocus: getReturnFocus,
|
||||
allowOutsideClick: (e) => {
|
||||
return (
|
||||
e.target instanceof Element &&
|
||||
|
|
@ -125,6 +142,7 @@
|
|||
document.addEventListener('pointerdown', handleOutsideInteraction, true);
|
||||
window.addEventListener('focusin', handleOutsideInteraction, true);
|
||||
modalElement.addEventListener('focusin', handleModalFocusIn);
|
||||
window.addEventListener('focusin', handleFocusOutside, true);
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
previousOverflow = document.body.style.overflow;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue