diff --git a/src/components/layout/LanguageSwitcher.tsx b/src/components/layout/LanguageSwitcher.tsx index f776dce..437f6ef 100644 --- a/src/components/layout/LanguageSwitcher.tsx +++ b/src/components/layout/LanguageSwitcher.tsx @@ -11,6 +11,7 @@ const LanguageSwitcher = () => { const pathname = usePathname(); const [isOpen, setIsOpen] = useState(false); const [isMobile, setIsMobile] = useState(false); + const [focusedIndex, setFocusedIndex] = useState(-1); const dropdownRef = useRef(null); const languages = [ @@ -30,8 +31,28 @@ const LanguageSwitcher = () => { }; const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === 'Escape') { - setIsOpen(false); + if (!isOpen) return; + + switch (e.key) { + case 'Escape': + setIsOpen(false); + setFocusedIndex(-1); + break; + case 'ArrowDown': + e.preventDefault(); + setFocusedIndex(prev => (prev + 1) % languages.length); + break; + case 'ArrowUp': + e.preventDefault(); + setFocusedIndex(prev => (prev - 1 + languages.length) % languages.length); + break; + case 'Enter': + e.preventDefault(); + if (focusedIndex >= 0) { + handleLanguageChange(languages[focusedIndex].code); + setFocusedIndex(-1); + } + break; } }; @@ -63,7 +84,10 @@ const LanguageSwitcher = () => { px-4 py-2 rounded-full transition-all duration-200 hover:bg-zinc-800/50 border border-transparent hover:border-zinc-800 hover:scale-105 active:scale-95" - onClick={() => setIsOpen(!isOpen)} + onClick={() => { + setIsOpen(!isOpen); + setFocusedIndex(-1); + }} aria-expanded={isOpen} aria-haspopup="listbox" aria-label="Select language" @@ -79,18 +103,21 @@ const LanguageSwitcher = () => { ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-95 pointer-events-none'}`} role="listbox" aria-label="Languages" + aria-activedescendant={focusedIndex >= 0 ? `lang-option-${languages[focusedIndex].code}` : undefined} onKeyDown={handleKeyDown} >
- {languages.map((lang) => ( + {languages.map((lang, index) => (