GitHub

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

PropTypeDefaultDescription
locales*Locale[]Available locales to switch between
value*stringCurrently selected locale code
onValueChange(locale: string) => voidCallback when locale changes
showLabelenumtrueShow locale label in trigger button
showFlagenumtrueShow flag emoji in trigger button
ariaLabelstringSelect languageAccessible label for screen readers
classNameenumCSS class applied to the element, or a function that returns a class based on the component’s state.
styleenumStyle applied to the element, or a function that returns a style object based on the component’s state.
variantenumoutline
sizeenumdefault
animatedenumtrueEnable hover scale and active press micro-interactions. Uses motion-safe media query to respect user preferences.
loadingenumfalseShow loading spinner and disable the button. When true, replaces iconStart with a spinner and sets aria-busy.
iconStartenumIcon to display at the start (left) of the button text. Automatically hidden when loading is true.
iconEndenumIcon to display at the end (right) of the button text. Remains visible during loading state.
fullWidthenumfalseMake the button expand to fill its container width.
glowenumfalseEnable animated gradient glow effect on hover. Adds decorative gradient lines below the button.
focusableWhenDisabledenumfalseWhether the button should be focusable when disabled.
nativeButtonenumtrueWhether 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>`).
renderenumAllows 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-label for screen reader description
  • Flag emojis are marked aria-hidden to avoid redundant announcements
  • Dropdown items are properly labeled with full locale names