diff --git a/src/renderer/src/components/LoginDialog.tsx b/src/renderer/src/components/LoginDialog.tsx index dbfa206..9b8e393 100644 --- a/src/renderer/src/components/LoginDialog.tsx +++ b/src/renderer/src/components/LoginDialog.tsx @@ -8,6 +8,8 @@ */ import React, { useState, useEffect, useRef } from 'react' +import FocusLock from 'react-focus-lock' +import { useDialogFocus } from '../hooks/useDialogFocus' interface LoginDialogProps { isOpen: boolean @@ -27,24 +29,44 @@ export const LoginDialog: React.FC = ({ const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [isLoggingIn, setIsLoggingIn] = useState(false) + const [errorMessage, setErrorMessage] = useState('') const usernameInputRef = useRef(null) + const dialogRef = useRef(null) + const errorRef = useRef(null) - // Focus on username input when dialog opens + // Setup focus management with useDialogFocus hook + const { focusLockProps } = useDialogFocus({ + isOpen, + dialogRef, + onClose: onCancel, + initialFocusSelector: 'input[type="text"]' // Focus username input initially + }) + + // Display error message with aria-live + const showError = (message: string) => { + setErrorMessage(message) + // Also call the original onError callback for backward compatibility + onError(message) + } + + // Focus on username input when dialog opens (maintained for compatibility) useEffect(() => { if (isOpen && usernameInputRef.current) { usernameInputRef.current.focus() } + // Clear error message when dialog opens + setErrorMessage('') }, [isOpen]) const handleLogin = async () => { if (!username.trim()) { - onError('请输入用户名') + showError('请输入用户名') usernameInputRef.current?.focus() return } if (!password.trim()) { - onError('请输入密码') + showError('请输入密码') return } @@ -53,7 +75,7 @@ export const LoginDialog: React.FC = ({ setIsLoggingIn(false) if (!success) { - onError('用户名或密码错误') + showError('用户名或密码错误') setPassword('') } } @@ -69,198 +91,86 @@ export const LoginDialog: React.FC = ({ if (!isOpen) return null return ( -
-
-
-

请登录

-

当前计算机:{computerName}

-
- -
-
- - setUsername(e.target.value)} - placeholder="请输入用户名" - disabled={isLoggingIn} - /> + +
+
+
+

+ 请登录 +

+

当前计算机:{computerName}

-
- - setPassword(e.target.value)} - placeholder="请输入密码" - disabled={isLoggingIn} - /> + {/* Error message area with aria-live for screen readers */} + {errorMessage && ( +
+ {errorMessage} +
+ )} + +
+
+ + setUsername(e.target.value)} + placeholder="请输入用户名" + disabled={isLoggingIn} + /> +
+ +
+ + setPassword(e.target.value)} + placeholder="请输入密码" + disabled={isLoggingIn} + /> +
-
-
- - -
+
+ + +
-
v1.0
+
v1.0
+
- - -
+ ) } export default LoginDialog + +// Styles are now handled by Tailwind classes in the component