| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- 'use client';
- import { useState, useRef, useEffect } from 'react';
- import { useI18n } from '@/lib/hooks/use-i18n';
- import { supportedLocales } from '@/lib/i18n';
- import { cn } from '@/lib/utils';
- interface LanguageSwitcherProps {
- /** Called when the dropdown opens, so parent can close sibling dropdowns */
- onOpen?: () => void;
- }
- export function LanguageSwitcher({ onOpen }: LanguageSwitcherProps) {
- const { locale, setLocale } = useI18n();
- const [open, setOpen] = useState(false);
- const ref = useRef<HTMLDivElement>(null);
- // Close on click outside
- useEffect(() => {
- if (!open) return;
- const handler = (e: MouseEvent) => {
- if (ref.current && !ref.current.contains(e.target as Node)) {
- setOpen(false);
- }
- };
- document.addEventListener('mousedown', handler);
- return () => document.removeEventListener('mousedown', handler);
- }, [open]);
- return (
- <div className="relative" ref={ref}>
- <button
- onClick={() => {
- const next = !open;
- setOpen(next);
- if (next) onOpen?.();
- }}
- className="flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-bold text-gray-500 dark:text-gray-400 hover:bg-white dark:hover:bg-gray-700 hover:text-gray-800 dark:hover:text-gray-200 hover:shadow-sm transition-all"
- >
- {supportedLocales.find((l) => l.code === locale)?.shortLabel ?? locale}
- </button>
- {open && (
- <div className="absolute top-full mt-2 right-0 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg overflow-hidden z-50 min-w-[120px]">
- {supportedLocales.map((l) => (
- <button
- key={l.code}
- onClick={() => {
- setLocale(l.code);
- setOpen(false);
- }}
- className={cn(
- 'w-full px-4 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors',
- locale === l.code &&
- 'bg-purple-50 dark:bg-purple-900/20 text-purple-600 dark:text-purple-400',
- )}
- >
- {l.label}
- </button>
- ))}
- </div>
- )}
- </div>
- );
- }
|