From e5fd019edff2cf06f202d97044163dcc58313a8e Mon Sep 17 00:00:00 2001 From: senke Date: Thu, 12 Feb 2026 21:55:25 +0100 Subject: [PATCH] a11y: skip link exists in App, ChatInput aria-label, sidebar focus trap, MiniPlayer aria-live Co-authored-by: Cursor --- apps/web/src/components/layout/Sidebar.tsx | 23 +++++++++++++++++-- .../features/chat/components/ChatInput.tsx | 1 + .../features/player/components/MiniPlayer.tsx | 18 ++++++++------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/apps/web/src/components/layout/Sidebar.tsx b/apps/web/src/components/layout/Sidebar.tsx index 6f802517f..27ec11fea 100644 --- a/apps/web/src/components/layout/Sidebar.tsx +++ b/apps/web/src/components/layout/Sidebar.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useState, useEffect } from 'react'; import { useLocation, Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { @@ -13,6 +13,7 @@ import { useSidebarNavigation } from '@/hooks/useSidebarNavigation'; import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { Tooltip } from '@/components/ui/tooltip'; +import { FocusTrap } from '@/components/ui/focus-trap'; interface SidebarProps { currentView?: string; @@ -90,12 +91,25 @@ const navItemInactiveClasses = const navItemActiveClasses = 'bg-primary/10 text-primary sidebar-active-indicator'; +const LG_BREAKPOINT = 1024; + export const Sidebar: React.FC = ({ currentView }) => { const { t } = useTranslation(); const location = useLocation(); const { sidebarOpen, setSidebarOpen } = useUIStore(); const { handleMobileNav, handleLogout } = useSidebarNavigation(); const navItems = useMemo(() => buildNavItems(t), [t]); + const [isMobile, setIsMobile] = useState(() => + typeof window !== 'undefined' ? window.innerWidth < LG_BREAKPOINT : false, + ); + + useEffect(() => { + const mq = window.matchMedia(`(max-width: ${LG_BREAKPOINT - 1}px)`); + const handler = () => setIsMobile(mq.matches); + handler(); + mq.addEventListener('change', handler); + return () => mq.removeEventListener('change', handler); + }, []); const activeView = currentView || @@ -113,7 +127,11 @@ export const Sidebar: React.FC = ({ currentView }) => { /> )} -