フォーカストラップ(モーダル用)
:LiTarget: 用途
モーダル内に Tab フォーカスを閉じ込める。a11y 必須機能。
:LiSparkle: 特徴
- Tab/Shift+Tab 制御
- 最初の要素にフォーカス
- モーダル閉じたら復元
- a11y 準拠
:LiCode: コード(コピペ用)
import { useEffect, useRef } from 'react';
const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
export function useFocusTrap<T extends HTMLElement>(active: boolean) {
const ref = useRef<T>(null);
useEffect(() => {
if (!active || !ref.current) return;
const previousFocus = document.activeElement as HTMLElement;
const elements = ref.current.querySelectorAll<HTMLElement>(FOCUSABLE);
const first = elements[0];
const last = elements[elements.length - 1];
first?.focus();
const onKey = (e: KeyboardEvent) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === first) { e.preventDefault(); last?.focus(); }
} else {
if (document.activeElement === last) { e.preventDefault(); first?.focus(); }
}
};
document.addEventListener('keydown', onKey);
return () => {
document.removeEventListener('keydown', onKey);
previousFocus?.focus();
};
}, [active]);
return ref;
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加