feat: improved locale selection (made button, use i18n)
This commit is contained in:
parent
bf4ed43f50
commit
e98a80666f
9 changed files with 291 additions and 44 deletions
|
@ -1,8 +1,9 @@
|
|||
"use client";
|
||||
"use client"
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { House, Link as LinkIcon, User, Phone, BookOpen, Music, Rss, X, Menu } from 'lucide-react';
|
||||
import React, { useState, useRef, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { House, Link as LinkIcon, User, Phone, BookOpen, Music, Rss, X, Menu, Globe, ChevronDown } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
interface NavItemProps {
|
||||
href: string;
|
||||
|
@ -19,6 +20,103 @@ const NavItem = ({ href, icon, children }: NavItemProps) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const LanguageSelector = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const languages = [
|
||||
{ code: 'en-US', name: 'English' },
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
setIsMobile(window.innerWidth < 1024);
|
||||
};
|
||||
|
||||
checkMobile();
|
||||
window.addEventListener('resize', checkMobile);
|
||||
return () => window.removeEventListener('resize', checkMobile);
|
||||
}, []);
|
||||
|
||||
const changeLanguage = (lng: string) => {
|
||||
i18n.changeLanguage(lng);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
setIsOpen(false);
|
||||
}
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
};
|
||||
|
||||
const buttonContent = (
|
||||
<>
|
||||
<Globe className="text-md mr-2" strokeWidth={2.5} size={20} />
|
||||
{languages.find(lang => lang.code === i18n.language)?.name || 'English'}
|
||||
{!isMobile && (
|
||||
<ChevronDown className={`w-4 h-4 ml-1 transform transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`} strokeWidth={2.5} size={20} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
onKeyDown={handleKeyDown}
|
||||
className={`flex items-center text-gray-300 hover:text-white hover:bg-gray-700 rounded-md px-3 py-2 transition-all duration-300 ${isMobile ? 'w-full' : ''}`}
|
||||
aria-expanded={isOpen}
|
||||
aria-haspopup="true"
|
||||
>
|
||||
{buttonContent}
|
||||
</button>
|
||||
{isOpen && (
|
||||
<div
|
||||
className={`${
|
||||
isMobile
|
||||
? 'relative mt-1 w-full bg-gray-800 rounded-md shadow-lg'
|
||||
: 'absolute right-0 mt-2 w-48 bg-gray-800 rounded-md shadow-lg z-50'
|
||||
}`}
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
aria-labelledby="language-menu"
|
||||
>
|
||||
{languages.map((lang) => (
|
||||
<button
|
||||
key={lang.code}
|
||||
onClick={() => changeLanguage(lang.code)}
|
||||
className={`block w-full text-left px-4 py-2 text-sm ${
|
||||
i18n.language === lang.code
|
||||
? 'text-white bg-gray-700'
|
||||
: 'text-gray-300 hover:text-white hover:bg-gray-700'
|
||||
}`}
|
||||
role="menuitem"
|
||||
>
|
||||
{lang.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Header() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
|
@ -41,7 +139,13 @@ export default function Header() {
|
|||
<NavItem href="/manifesto" icon={BookOpen}>Manifesto</NavItem>
|
||||
<NavItem href="/music" icon={Music}>Music</NavItem>
|
||||
<NavItem href="https://disfunction.blog" icon={Rss}>Blog</NavItem>
|
||||
<div className="lg:hidden">
|
||||
<LanguageSelector />
|
||||
</div>
|
||||
</ul>
|
||||
<div className="hidden lg:block">
|
||||
<LanguageSelector />
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue