Started working on adding mobile buzzers, a lot of rewriting
This commit is contained in:
47
src/lib/utils/focusTrap.ts
Normal file
47
src/lib/utils/focusTrap.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
// Focus trap utility for modals
|
||||
export function trapFocus(node: HTMLElement) {
|
||||
const focusableSelectors = [
|
||||
'button:not([disabled])',
|
||||
'input:not([disabled])',
|
||||
'select:not([disabled])',
|
||||
'textarea:not([disabled])',
|
||||
'a[href]',
|
||||
'[tabindex]:not([tabindex="-1"])',
|
||||
].join(', ');
|
||||
|
||||
function getFocusableElements() {
|
||||
return Array.from(node.querySelectorAll<HTMLElement>(focusableSelectors));
|
||||
}
|
||||
|
||||
function handleKeydown(e: KeyboardEvent) {
|
||||
if (e.key !== 'Tab') return;
|
||||
|
||||
const focusable = getFocusableElements();
|
||||
if (focusable.length === 0) return;
|
||||
|
||||
const first = focusable[0];
|
||||
const last = focusable[focusable.length - 1];
|
||||
|
||||
if (e.shiftKey && document.activeElement === first) {
|
||||
e.preventDefault();
|
||||
last.focus();
|
||||
} else if (!e.shiftKey && document.activeElement === last) {
|
||||
e.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Focus first element on mount
|
||||
const focusable = getFocusableElements();
|
||||
if (focusable.length > 0) {
|
||||
focusable[0].focus();
|
||||
}
|
||||
|
||||
node.addEventListener('keydown', handleKeydown);
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener('keydown', handleKeydown);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user