Files
awoooi/apps/web/src/components/shared/language-switcher.tsx
OG T 4d46e6b9a7
Some checks failed
E2E Health Check / e2e-health (push) Successful in 17s
CD Pipeline / build-and-deploy (push) Has been cancelled
style(web): 全站 font-mono → font-body (DM Mono 設計系統套用)
45 個 component + 6 個 page 統一從舊 font-mono 遷移到
font-body (DM Mono),確保設計系統一致性。

font-body = DM Mono (等寬),視覺效果相同但走新設計 token。
保留: font-heading (Syne)、font-dot-matrix (VT323/DSEG7)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 09:37:03 +08:00

99 lines
2.7 KiB
TypeScript

'use client'
/**
* LanguageSwitcher - 賽博風語系切換器
*
* Nothing.tech 風格極簡設計
* 支援 EN / 繁中 切換
*/
import { useLocale } from 'next-intl'
import { useRouter, usePathname, locales, localeShortNames, type Locale } from '@/i18n/routing'
import { cn } from '@/lib/utils'
interface LanguageSwitcherProps {
className?: string
}
export function LanguageSwitcher({ className }: LanguageSwitcherProps) {
const locale = useLocale() as Locale
const router = useRouter()
const pathname = usePathname()
const handleSwitch = (newLocale: Locale) => {
if (newLocale === locale) return
router.replace(pathname, { locale: newLocale })
}
return (
<div
className={cn(
'px-1 py-1 flex items-center gap-1 rounded-button',
'bg-nothing-gray-100 border border-nothing-gray-200',
className
)}
>
{locales.map((loc) => {
const isActive = loc === locale
return (
<button
key={loc}
onClick={() => handleSwitch(loc)}
className={cn(
'px-3 py-1.5 rounded-sm font-body text-xs transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-nothing-gray-400',
isActive
? 'bg-nothing-gray-900 text-nothing-white'
: 'text-nothing-gray-600 hover:text-nothing-gray-900 hover:bg-nothing-gray-200'
)}
aria-label={`Switch to ${localeShortNames[loc]}`}
aria-pressed={isActive}
>
{localeShortNames[loc]}
</button>
)
})}
</div>
)
}
/**
* LanguageSwitcherCompact - 更緊湊的版本
* 只顯示當前語系,點擊切換
*/
export function LanguageSwitcherCompact({ className }: LanguageSwitcherProps) {
const locale = useLocale() as Locale
const router = useRouter()
const pathname = usePathname()
const handleToggle = () => {
const currentIndex = locales.indexOf(locale)
const nextIndex = (currentIndex + 1) % locales.length
const newLocale = locales[nextIndex]
router.replace(pathname, { locale: newLocale })
}
return (
<button
onClick={handleToggle}
className={cn(
'px-3 py-1.5 rounded-button',
'bg-nothing-gray-100 border border-nothing-gray-200',
'font-body text-xs text-nothing-gray-600',
'hover:text-nothing-gray-900 hover:bg-nothing-gray-200',
'transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-nothing-gray-400',
className
)}
aria-label="Toggle language"
>
<span className="flex items-center gap-2">
<span className="w-1.5 h-1.5 rounded-full bg-status-healthy" />
{localeShortNames[locale]}
</span>
</button>
)
}