mirror of
https://github.com/usebruno/bruno.git
synced 2024-11-21 23:43:15 +01:00
* enhance useFocusTrap: implemented focus trapping, hide non-focusable elements * add reference link
This commit is contained in:
parent
e019a96cd5
commit
563683b5c1
@ -1,24 +1,28 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
const useFocusTrap = (modalRef) => {
|
const useFocusTrap = (modalRef) => {
|
||||||
const firstFocusableElementRef = useRef(null);
|
|
||||||
const lastFocusableElementRef = useRef(null);
|
|
||||||
|
|
||||||
|
// refer to this implementation for modal focus: https://stackoverflow.com/a/38865836
|
||||||
|
const focusableSelector = 'a[href], area[href], input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex]:not([tabindex="-1"]), *[contenteditable]';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const modalElement = modalRef.current;
|
const modalElement = modalRef.current;
|
||||||
if (!modalElement) return;
|
if (!modalElement) return;
|
||||||
|
|
||||||
const focusableElements = modalElement.querySelectorAll(
|
const focusableElements = Array.from(document.querySelectorAll(focusableSelector));
|
||||||
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
const modalFocusableElements = Array.from(modalElement.querySelectorAll(focusableSelector));
|
||||||
);
|
const elementsToHide = focusableElements.filter(el => !modalFocusableElements.includes(el));
|
||||||
|
|
||||||
if (focusableElements.length === 0) return;
|
// Hide elements outside the modal
|
||||||
|
elementsToHide.forEach(el => {
|
||||||
|
const originalTabIndex = el.getAttribute('tabindex');
|
||||||
|
el.setAttribute('data-tabindex', originalTabIndex || 'inline');
|
||||||
|
el.setAttribute('tabindex', -1);
|
||||||
|
});
|
||||||
|
|
||||||
const firstElement = focusableElements[0];
|
// Set focus to the first focusable element in the modal
|
||||||
const lastElement = focusableElements[focusableElements.length - 1];
|
const firstElement = modalFocusableElements[0];
|
||||||
|
const lastElement = modalFocusableElements[modalFocusableElements.length - 1];
|
||||||
firstFocusableElementRef.current = firstElement;
|
|
||||||
lastFocusableElementRef.current = lastElement;
|
|
||||||
|
|
||||||
const handleKeyDown = (event) => {
|
const handleKeyDown = (event) => {
|
||||||
if (event.key === 'Tab') {
|
if (event.key === 'Tab') {
|
||||||
@ -36,6 +40,12 @@ const useFocusTrap = (modalRef) => {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
modalElement.removeEventListener('keydown', handleKeyDown);
|
modalElement.removeEventListener('keydown', handleKeyDown);
|
||||||
|
|
||||||
|
// Restore original tabindex values
|
||||||
|
elementsToHide.forEach(el => {
|
||||||
|
const originalTabIndex = el.getAttribute('data-tabindex');
|
||||||
|
el.setAttribute('tabindex', originalTabIndex === 'inline' ? '' : originalTabIndex);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}, [modalRef]);
|
}, [modalRef]);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user