fix(web): address CodeRabbit review feedback
Fixes issues identified in PR #3076: 1. mock-server.mjs: Fix HTTP line ending escape sequence - Changed `\\r\\n\\r\\n` to `\r\n\r\n` for proper HTTP CRLF terminators 2. App.tsx: Add accessibility attributes to pairing form - Added aria-label, aria-invalid, aria-describedby to input - Added id="pairing-error" and role="alert" to error message 3. Header.tsx: Add accessible name to logout button - Added aria-label for screen readers on mobile (icon-only) view 4. Layout.tsx: Guard localStorage access with try-catch - Prevents runtime errors when storage is blocked/unavailable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3f5c57634b
commit
c280ae5045
@ -338,7 +338,7 @@ wsServer.on('connection', (socket) => {
|
||||
server.on('upgrade', (req, socket, head) => {
|
||||
const url = new URL(req.url, `http://${req.headers.host}`);
|
||||
if (url.pathname !== '/ws/chat' || !isAuthorized(req)) {
|
||||
socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');
|
||||
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -87,6 +87,9 @@ function PairingDialog({
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
aria-label={translate('auth.enter_code')}
|
||||
aria-invalid={Boolean(error)}
|
||||
aria-describedby={error ? 'pairing-error' : undefined}
|
||||
value={code}
|
||||
onChange={(e) => setCode(e.target.value)}
|
||||
placeholder={translate('auth.code_placeholder')}
|
||||
@ -95,7 +98,7 @@ function PairingDialog({
|
||||
autoFocus
|
||||
/>
|
||||
{error && (
|
||||
<p className="mb-4 text-center text-sm text-rose-300">{error}</p>
|
||||
<p id="pairing-error" role="alert" className="mb-4 text-center text-sm text-rose-300">{error}</p>
|
||||
)}
|
||||
<button
|
||||
type="submit"
|
||||
|
||||
@ -67,6 +67,7 @@ export default function Header({ onToggleSidebar }: HeaderProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={logout}
|
||||
aria-label={t('auth.logout')}
|
||||
className="flex items-center gap-1 rounded-lg border border-[#2b4f97] bg-[#091937]/75 px-2.5 py-1.5 text-xs text-[#c4d8ff] transition hover:border-[#4f83ff] hover:text-white sm:gap-1.5 sm:px-3 sm:text-sm"
|
||||
>
|
||||
<LogOut className="h-4 w-4" />
|
||||
|
||||
@ -11,14 +11,22 @@ export default function Layout() {
|
||||
if (typeof window === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
return window.localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === '1';
|
||||
try {
|
||||
return window.localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === '1';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
const toggleSidebarCollapsed = () => {
|
||||
setSidebarCollapsed((prev) => {
|
||||
const next = !prev;
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(SIDEBAR_COLLAPSED_KEY, next ? '1' : '0');
|
||||
try {
|
||||
window.localStorage.setItem(SIDEBAR_COLLAPSED_KEY, next ? '1' : '0');
|
||||
} catch {
|
||||
// Storage unavailable, ignore
|
||||
}
|
||||
}
|
||||
return next;
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user