LocaleSwitcher
SM, under 950B gzippedA native, per-option lang-tagged language switcher.
- Category
- Internationalisation
- Budget
- sm, single-purpose control
- Runtime deps
- None
Preview
This is the exact fixture the conformance suite renders in CI. Switch the language to see the component mirror and reformat.
Install
npx shadcn@latest add https://kata-ui-rho.vercel.app/r/locale-switcher.jsonCopies the source into your project. Pulls in 1 primitive: cn.
Source
"use client";
import { useId } from "react";
import { cn } from "../lib/cn";
export interface LocaleOption {
tag: string;
/** The language's own name for itself — "Português", not "Portuguese". */
nativeName: string;
}
export interface LocaleSwitcherProps {
options: LocaleOption[];
value: string;
onChange: (tag: string) => void;
label?: string;
className?: string;
}
/**
* A native `<select>`, deliberately not a custom dropdown: this is the one
* control every platform already has a fully localised, fully accessible,
* fully keyboard- and touch-native implementation of, including on the
* lowest-end devices this library is built for. Each option's `lang`
* attribute matches its own tag so a screen reader can switch pronunciation
* per option rather than reading every name in the page's base language.
*/
export function LocaleSwitcher({ options, value, onChange, label = "Language", className }: LocaleSwitcherProps) {
const id = useId();
return (
<div className={cn("inline-flex flex-col gap-1", className)}>
<label htmlFor={id} className="text-sm font-medium">
{label}
</label>
<select
id={id}
value={value}
onChange={(event) => onChange(event.target.value)}
className="rounded-md border border-neutral-300 bg-white px-2 py-1.5 text-sm dark:border-neutral-700 dark:bg-neutral-900"
>
{options.map((option) => (
<option key={option.tag} value={option.tag} lang={option.tag}>
{option.nativeName}
</option>
))}
</select>
</div>
);
}
What CI checks
- Bundled, minified and gzipped against its tier budget
- Audited by axe in the state previewed above
- Rendered through react-dom/server with no browser globals
- Scanned for network calls, dangerous sinks, and unguarded animation