shadcn.io is not affiliated with official shadcn/ui
Language Switcher Navbar Block for React
A navbar whose language button opens a searchable list of twelve languages in their own scripts; choosing one rewrites the bar's links and action, and choosing Arabic flips the whole bar right to left.
Installation
Overview
A localized navbar for React with Base UI, for a language-course platform called Lingotrail. One bar between the page's rails: the wordmark, four links (Courses, Practice, Pricing, Community), a language button that shows the current language in its own script, and a Shine Button. The button opens a searchable list over the page: twelve languages, each written in its own script with its lang and its English name beside it, three suggested ones first, then the rest, a check on the current one and a field that narrows both groups by either name. Choosing a language rewrites the links, the button and the action in it, says so in a polite line, closes the list and returns focus to the button. Choosing Arabic also sets dir="rtl" on the bar and on the library's direction provider, so the bar, the phone sheet and the list all flip. Every version of a label shares one cell, so nothing moves when you choose. On a phone the list opens as a drawer from the bottom. It's built from Popover, Command, Drawer, Sheet, Guides, Shine Button and Button, with your theme's tokens for every colour. For multilingual sites that want a picker that scales past six flags.
FAQ
How do I add a language or change the words?
Every language's strings are one typed object in the LANGUAGES array at the top of the file: its code, its name in its own script (autonym) and in English, the button's name, the four links, the cta, whether it reads from the end (rtl) and whether the list leads with it (suggested). Add an object and it appears in the list, in the search and in the bar; the unseen copies that size each label are built from the same array. The list's own words (the search placeholder, the group names, "No language found.") are English constants in Picker; translate them the same way if your picker should localize too. In an app, replace setCode with your router's locale change.
How does the right-to-left flip work?
rtl: true on a language sets dir="rtl" on the header and passes it to the catalog's direction provider, so the bar mirrors (the wordmark moves to the end, the actions to the start) and the library's own parts follow: the list, the drawer and the sheet are portalled out of the header, so each carries dir itself. Logical classes (ms-auto, -me-1.5) do the rest. The wordmark keeps its direction because it's artwork, and the picker's English names stay in their own direction inside the mirrored list.
How does it work with a keyboard and a screen reader?
The links sit in a nav named Main after the wordmark. The language button is named in the current language ("Sprache: Deutsch"), says whether the list is open and which list it controls, and opens it on Enter or Space; focus lands in the search field. Typing narrows the list by native name, English name or code (accents ignored); the arrow keys move through the rows, Enter chooses, and Escape closes the list and puts focus back on the button. The current language says "current language" to screen readers as well as showing a check, each row carries its lang so it is read in the right voice, and after a choice a hidden status line says "Language: Deutsch".
The list is a command built on cmdk; the first match is highlighted as you type, and Enter chooses it.
How does it work on a phone?
Below the md breakpoint the language button becomes an icon (its name is still spoken) and opens a drawer from the bottom with the same search and the same twelve rows; choosing a language closes it and returns focus to the icon. Below lg the links and the action fold into a menu button that opens a sheet from the top, in the current language and, for Arabic, mirrored. At 320 pixels the bar holds the wordmark, the icon and the menu button, and nothing wraps.
Why does nothing move when I choose a language?
A label in one language is wider than in another ("Empezar ahora" against "Başla"), which would shift the buttons beside it. Each label (the four links, the action and the button's text) sits in one grid cell together with an unseen copy of every other version, so the cell is always as wide as the widest. The unseen copies are hidden from assistive technology and from the keyboard. The bar is 64 pixels tall (56 on a phone) in every language.
What moves, and what happens with reduced motion?
Nothing moves on load or when the language changes: the words are swapped, not animated. The list fades and grows from the button, the drawer and the sheet slide in, and a band of light sweeps across the action on hover and keyboard focus. With reduced motion the list, the drawer and the sheet appear without animating and the light fades in where it stands.
Related
- Pro
Theme Toggle Navbar
Surface and themeA navbar whose theme button opens the new theme as a circle growing from the button you pressed (View Transitions, guarded), with a menu to pick Light, Dark or System by name.
- Pro
Account Menu Navbar
Accounts and scopesAn app bar with an account button behind a split divider that opens a menu: an identity header with plan badge and storage bar, a Switch account radio list, and Profile, Settings, Billing and Sign out.
- Pro
SaaS Marketing Navbar
Mega menusA one-bar marketing navbar for a product roadmap tool: a wordmark, a Product menu of four areas with icons and one-line descriptions, plain links with the current page marked, Sign in and a Shine Button, and a sheet with the same links on phones.
- Pro
Language Selector Footer
PreferencesA footer for a meeting-notes tool whose segmented control (EN, FR, DE, ES) rewrites the footer's own words, with three link groups and a legal row.
- Pro
Multilingual Footer
PreferencesA footer for a help-desk inbox whose Select of six languages rewrites its words and flips it to right-to-left when Arabic is chosen.
- Pro
A language pill for a travel-guide site: a globe, "Guides in" and a button naming the current language, opening a popover of six languages written in their own scripts.