Locale Switcher
A dropdown component for switching between locales/languages.
Basic Usage
Loading...
Locale SwitcherLanguage selection dropdown
Installation
The LocaleSwitcher component is part of the UI package.
Usage
import { LocaleSwitcher } from "@mordecai-design-system/ui"const locales = [
{ code: 'en', label: 'English', flag: '🇺🇸' },
{ code: 'fr', label: 'Français', flag: '🇫🇷' },
{ code: 'es', label: 'Español', flag: '🇪🇸' },
]
<LocaleSwitcher
locales={locales}
value={currentLocale}
onValueChange={setCurrentLocale}
/>Examples
Basic
<LocaleSwitcher
locales={[
{ code: 'en', label: 'English' },
{ code: 'fr', label: 'Français' },
]}
value="en"
onValueChange={(locale) => console.log(locale)}
/>With Flags
<LocaleSwitcher
locales={[
{ code: 'en', label: 'English', flag: '🇺🇸' },
{ code: 'fr', label: 'Français', flag: '🇫🇷' },
{ code: 'de', label: 'Deutsch', flag: '🇩🇪' },
]}
value="en"
onValueChange={setLocale}
showFlag
/>Icon Only
<LocaleSwitcher
locales={locales}
value="en"
onValueChange={setLocale}
showLabel={false}
/>With Next.js i18n
import { useRouter, usePathname } from 'next/navigation'
function LanguageSwitcher() {
const router = useRouter()
const pathname = usePathname()
const currentLocale = pathname.split('/')[1] || 'en'
const handleChange = (locale: string) => {
const newPath = pathname.replace(/^\/[a-z]{2}/, `/${locale}`)
router.push(newPath)
}
return (
<LocaleSwitcher
locales={locales}
value={currentLocale}
onValueChange={handleChange}
/>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| locales* | Locale[] | — | Available locales to switch between |
| value* | string | — | Currently selected locale code |
| onValueChange | (locale: string) => void | — | Callback when locale changes |
| showLabel | enum | true | Show locale label in trigger button |
| showFlag | enum | true | Show flag emoji in trigger button |
| ariaLabel | string | Select language | Accessible label for screen readers |
| className | enum | — | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | enum | — | Style applied to the element, or a function that returns a style object based on the component’s state. |
| variant | enum | outline | — |
| size | enum | default | — |
| animated | enum | true | Enable hover scale and active press micro-interactions. Uses motion-safe media query to respect user preferences. |
| loading | enum | false | Show loading spinner and disable the button. When true, replaces iconStart with a spinner and sets aria-busy. |
| iconStart | enum | — | Icon to display at the start (left) of the button text. Automatically hidden when loading is true. |
| iconEnd | enum | — | Icon to display at the end (right) of the button text. Remains visible during loading state. |
| fullWidth | enum | false | Make the button expand to fill its container width. |
| glow | enum | false | Enable animated gradient glow effect on hover. Adds decorative gradient lines below the button. |
| focusableWhenDisabled | enum | false | Whether the button should be focusable when disabled. |
| nativeButton | enum | true | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (e.g. `<div>`). |
| render | enum | — | Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
Types
interface Locale {
code: string // e.g., 'en', 'fr'
label: string // e.g., 'English', 'Français'
flag?: string // e.g., '🇺🇸', '🇫🇷'
}Accessibility
- Uses
aria-labelfor screen reader description - Flag emojis are marked
aria-hiddento avoid redundant announcements - Dropdown items are properly labeled with full locale names