Skip to content

LangSwitch

The language switcher for the header, the mobile menu and the footer.

import { LangSwitch } from '@zitdevs/ui';

The header and the mobile menu:

Select languageENES

The footer, on the inverse field, on a Spanish page:

import * as es from '@zitdevs/ui/labels/es';
const languages = [
{ code: 'en', label: 'English', href: '/services' },
{ code: 'es', label: 'Español', href: '/es/servicios' },
];
<LangSwitch current="en" languages={languages} />
<LangSwitch variant="footer" current="es" labels={es.langSwitch} languages={languages} />

Through a router’s link, such as Next’s Link, with linkAs. See Router links.

import Link from 'next/link';
<LangSwitch linkAs={Link} current="en" languages={languages} />;
Prop Type Default Notes
languages readonly LangSwitchLanguage[] required The page’s translations, in display order. A language left out is not offered.
current string required The code of the page’s language: aria-current="page".
variant 'header' | 'mobile' | 'footer' 'header' header: codes only. mobile: a visible label, 44px targets. footer: label, full names.
id string language-<variant> Builds the label’s id, <id>-label. Only needed for two switchers of one variant on a page.
labels Partial<LangSwitchLabels> English { selectLanguage, languageLabel }. es.langSwitch from labels/es.
linkAs LinkComponent 'a' Renders each link: Next’s Link, or any router’s.
ref Ref<HTMLDivElement> — The group.
className string — Placement.
anything else <div> attributes — Except role, id and the group’s name, which it sets.

LangSwitchLanguage is { code: string; label: string; href: string; lang?: string }: code is shown uppercased in the header and mobile variants, label is the language’s own name, shown in the footer, and lang is the BCP 47 tag of the link’s hreflang and lang, code by default. Each code is a React key, so no two may be the same.

Exported types: LangSwitchProps, LangSwitchLanguage, LangSwitchVariant, LangSwitchLabels, and the label sets langSwitchLabels.

  • A role="group": named “Select language” in the header, and by its visible label in the mobile menu (“Select language”) and the footer (“Language:”).
  • Every entry is a real link to the translated page with hreflang and lang, so a screen reader pronounces “Español” in Spanish and crawlers know what it is. The current language carries aria-current="page".
  • The separators are hidden. Each link draws the kit’s focus ring itself.

It needs none: links in a group, rendered as a Server Component, through a router’s link too.

The chrome follows labels, not current: a Spanish page passes labels={es.langSwitch}, or its own dictionary. The language names and codes are data in languages, since a language’s own name does not translate. See Languages.

Header and mobile: muted at rest, ink on hover and current, primary under the current language, border-strong separators. Footer, on the inverse field: on-inverse-quiet at 60% at rest and for the label, on-inverse on hover and current, accent under the current language, on-inverse-quiet at 35% for the separators (hidden decoration).