Component

Language Switcher

Language selector dropdown with country flags, search functionality, grouped languages, and RTL support.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

Interactive preview
Open preview
9:41 100%
devsnips.site/library/tailwind/components/dropdowns/language-switcher/
fluid · no fixed width 100%
No dependencies Production-ready

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Dropdowns/language-switcher
registry path: Tailwind/Components/Dropdowns/language-switcher

Source

Implementation

code.html
<!-- Language Switcher -->
<div class="relative inline-block">
  <button
    id="lang-button"
    class="flex items-center gap-2 px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
    onclick="toggleDropdown('lang-menu')"
  >
    <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129"></path>
    </svg>
    <span id="current-lang">English</span>
    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
    </svg>
  </button>

  <div
    id="lang-menu"
    class="hidden absolute left-0 z-20 mt-2 w-64 bg-white rounded-xl shadow-xl border border-gray-200 overflow-hidden"
  >
    <div class="py-2">
      <!-- Search -->
      <div class="px-3 pb-3">
        <div class="relative">
          <svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
          </svg>
          <input
            type="text"
            placeholder="Search languages..."
            class="w-full pl-9 pr-4 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
            oninput="filterLanguages(this.value)"
          />
        </div>
      </div>

      <!-- Popular Languages -->
      <div class="px-3 pb-2">
        <p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Popular</p>
      </div>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="English"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇺🇸</span>
          <span>English</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Spanish"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇪🇸</span>
          <span>Español</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="French"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇫🇷</span>
          <span>Français</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="German"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇩🇪</span>
          <span>Deutsch</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <!-- Divider -->
      <div class="border-t border-gray-100 my-2"></div>

      <!-- More Languages -->
      <div class="px-3 pb-2">
        <p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">More Languages</p>
      </div>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Portuguese"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇧🇷</span>
          <span>Português</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Japanese"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇯🇵</span>
          <span>日本語</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Chinese"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇨🇳</span>
          <span>中文</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Korean"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇰🇷</span>
          <span>한국어</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>

      <button
        class="lang-option w-full flex items-center justify-between px-4 py-2.5 text-sm text-gray-700 hover:bg-blue-50 transition-colors"
        data-lang="Arabic"
        onclick="selectLanguage(this)"
      >
        <div class="flex items-center gap-3">
          <span class="text-xl">🇸🇦</span>
          <span>العربية</span>
        </div>
        <svg class="w-4 h-4 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
        </svg>
      </button>
    </div>
  </div>
</div>

<script>
  function toggleDropdown(id) {
    document.getElementById(id).classList.toggle('hidden');
  }

  function selectLanguage(element) {
    const lang = element.getAttribute('data-lang');
    document.getElementById('current-lang').textContent = lang;
    
    document.querySelectorAll('.lang-option').forEach(opt => {
      opt.classList.remove('bg-blue-50');
      opt.querySelector('.check-icon').classList.add('hidden');
    });
    
    element.classList.add('bg-blue-50');
    element.querySelector('.check-icon').classList.remove('hidden');
    
    toggleDropdown('lang-menu');
  }

  function filterLanguages(query) {
    const normalizedQuery = query.toLowerCase();
    document.querySelectorAll('.lang-option').forEach(option => {
      const lang = option.getAttribute('data-lang').toLowerCase();
      if (lang.includes(normalizedQuery)) {
        option.classList.remove('hidden');
      } else {
        option.classList.add('hidden');
      }
    });
  }

  document.addEventListener('click', function(event) {
    const container = document.querySelector('.relative.inline-block');
    if (!container.contains(event.target)) {
      document.getElementById('lang-menu').classList.add('hidden');
    }
  });
</script>
217 lines UTF-8 · LF · Spaces: 2
DevSnips AI ready Claude · Cursor · Windsurf

Agent skill & Model Context Protocol

Pass this component straight into your AI workflow. DevSnips exposes each resource as a structured, addressable registry entry, so your agent installs the real files instead of approximating them.

devsnips://components/dropdowns/language-switcher
Prompt instruction
I want to use this DevSnips resource in production:

Page:
https://devsnips.site/library/tailwind/components/dropdowns/language-switcher/

Install: npx devsnips add
Tailwind/Components/Dropdowns/language-switcher

This is the Language Switcher — Language selector dropdown with country flags, search functionality, grouped languages, and RTL support.

Use this DevSnips resource as the starting point for my project.
Adapt it to my project's stack and conventions, fix any issues,
and make it production-ready while preserving its intended design
and behavior.

Paste into ChatGPT, Claude or your agent — it already carries the page URL and the exact install path.

Resource URI
devsnips://components/dropdowns/language-switcher