if authmodal is up, cursor is already in it
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user