Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Language Switcher Command Menu Block for React

A language-learning app's language menu as a command menu shown open above the language button in a lesson page's foot: ten languages by their own names with lang and dir set, a completeness bar and percent, search in any script, and a lesson page whose labels flip.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let people find their language in their own words with this language switcher command menu for React with Base UI. It opens from the Lessons page of Tonguefield, a language-learning app, whose header holds an outline field with its ⌘ K cap, and the page is drawn under a soft scrim inside a hairline frame with a plus mark on each corner: a lesson with a title, a goal and two buttons, over a foot whose language button the menu rises from. The menu is the catalog Command. Ten languages are rows, each with its own name in its own script, set with its lang and dir="rtl" for Hebrew and Arabic, its English name, a thin Progress bar and "92% translated". Typing in any script matches either name, with or without accents, so "espanol", "Español" and "日本" all find their language. Choosing one flips four labels on the drawn lesson page among typed translations and sets the page's lang and dir; the foot button names the language in its own script. There are no flags and no emoji. Nothing is saved. For preview the menu is drawn open in place when the page loads; the field, or Ctrl or ⌘ K while focus is in the block, opens the real command dialog with the same rows and query. For learning apps, documentation sites, stores and any product that speaks more than one language.

FAQ

Why is the menu already open, and what do I keep?

So you can see it without a click. On load the menu is the Command drawn inline above the drawn language button, in a plain shell that is not modal, so nothing is trapped, hidden or focused and the page around the preview keeps working. The header's field opens the real command dialog, modal, with its focus trap, Escape and focus return, and the inline copy stays closed until a reload. Both show the same Palette and share the block's state, so the language you chose and what you typed in the copy are in the real dialog. In your app keep the dialog and drop the copy: the "in-place" state, the scrim with its shell and the Escape and blur effects.

Why does each language show its own name?

Because someone who cannot read the interface's language can still find theirs: Deutsch, Español, 日本語, עברית, العربية. Each native name is set with its own lang, so screen readers pronounce it and browsers pick the right font, and Hebrew and Arabic also carry dir="rtl", so their letters sit in the right order inside a left-to-right row. The English name sits under it for everyone else.

What changes on the page when I choose one?

Four labels on the drawn lesson page (the title, the goal and the two buttons) switch among typed translations, and the page's wrapper gets the language's lang and dir, so choosing Hebrew or Arabic mirrors the layout. The foot button shows the language's own name. The drawing is hidden from assistive technology, so the status line says what was set. The translations are typed, in this demo only; in your app they come from your message catalogs.

What stays local, and how do I wire it?

All of it. Nothing is saved, no locale cookie is set and no page reloads. The completeness figures are typed data; in your app they come from your translation tool. pick is where you would set the locale (a route, a cookie or a user setting), and the status line is the one polite live region.

Is it accessible from the keyboard?

Yes. Type to search, the arrow keys move, Enter chooses the highlighted language and Escape closes the menu and puts focus on the field; Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The current language is ticked and says so for screen readers. The rows are options of a cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself.

How does it look on a phone?

The copy shown on load docks to the top of the page at full width, so the keyboard does not cover the foot; the bars go and the percent words stay, and the key hints go while the count stays. The real dialog keeps the Command dialog's own phone layout.

  • Pro

    Language Switcher Navbar

    Accounts and scopes

    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.

  • Pro

    A docs site's settings page with its language dialog shown open: eight languages named in their own script, each with a translation coverage bar, and an Apply button that re-reads the landing page behind it, flipping it right-to-left for Arabic.

  • Pro

    A team intranet's profile page with its language and region dialog shown open: a Language tab with a searchable list of eight languages, a Region tab with country, first day of the week and clock, and a live preview that reformats a sample date, time, number and amount with Intl.

  • Pro

    A localisation platform's string finder as a command menu shown open under a band of language chips with their coverage: keys with their text in the chosen language or the word Missing, a Missing only switch and a copy key button.

  • Pro

    An agency billing portal's account switcher as a command menu shown open under the account chip: four accounts with initials, role and plan, a tick on the current one, the keys 1 to 4 to switch straight to an account, and the chip and status line that follow the choice.

  • Pro

    A bank back office's navigation menu shown open: 24 pages in three levels, each row the name over its whole path, a search that reads the path by the start of each word, and a tick on the page you are on.