if authmodal is up, cursor is already in it

This commit is contained in:
jackiettran
2025-12-18 18:43:08 -05:00
parent 38e0b6a16d
commit 996e815d57

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useRef, useCallback } from "react";
import { useAuth } from "../contexts/AuthContext"; import { useAuth } from "../contexts/AuthContext";
import PasswordStrengthMeter from "./PasswordStrengthMeter"; import PasswordStrengthMeter from "./PasswordStrengthMeter";
import PasswordInput from "./PasswordInput"; import PasswordInput from "./PasswordInput";
@@ -27,6 +27,7 @@ const AuthModal: React.FC<AuthModalProps> = ({
const [showVerificationModal, setShowVerificationModal] = useState(false); const [showVerificationModal, setShowVerificationModal] = useState(false);
const { login, register } = useAuth(); const { login, register } = useAuth();
const modalRef = useRef<HTMLDivElement>(null);
// Update mode when modal is opened with different initialMode // Update mode when modal is opened with different initialMode
useEffect(() => { useEffect(() => {
@@ -35,6 +36,54 @@ const AuthModal: React.FC<AuthModalProps> = ({
} }
}, [show, initialMode]); }, [show, initialMode]);
// Focus trapping for accessibility
const handleKeyDown = useCallback((e: KeyboardEvent) => {
if (e.key !== "Tab" || !modalRef.current) return;
const focusableElements = modalRef.current.querySelectorAll<HTMLElement>(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const focusableArray = Array.from(focusableElements).filter(
(el) => !el.hasAttribute("disabled") && el.offsetParent !== null
);
if (focusableArray.length === 0) return;
const firstElement = focusableArray[0];
const lastElement = focusableArray[focusableArray.length - 1];
if (e.shiftKey) {
// Shift + Tab: if on first element, go to last
if (document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
}
} else {
// Tab: if on last element, go to first
if (document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
}, []);
// Set up focus trap and initial focus when modal is shown
useEffect(() => {
if (show && !showForgotPassword && !showVerificationModal) {
document.addEventListener("keydown", handleKeyDown);
// Focus the first input element when modal opens
if (modalRef.current) {
const firstInput = modalRef.current.querySelector<HTMLElement>('input');
firstInput?.focus();
}
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}
}, [show, showForgotPassword, showVerificationModal, handleKeyDown]);
const resetModal = () => { const resetModal = () => {
setError(""); setError("");
setEmail(""); setEmail("");
@@ -119,7 +168,7 @@ const AuthModal: React.FC<AuthModalProps> = ({
style={{ backgroundColor: "rgba(0,0,0,0.5)" }} style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
> >
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">
<div className="modal-content"> <div className="modal-content" ref={modalRef}>
<div className="modal-header border-0 pb-0"> <div className="modal-header border-0 pb-0">
<button <button
type="button" type="button"