Component

Theme Switcher

Theme switcher dropdown with light, dark, system, and sepia themes plus accent color selection.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

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

Source

Implementation

code.html
<!-- Theme Switcher -->
<div class="relative inline-block">
  <button
    id="theme-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('theme-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="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
    </svg>
    <span>Theme</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="theme-menu"
    class="hidden absolute left-0 z-20 mt-2 w-72 bg-white rounded-xl shadow-xl border border-gray-200 overflow-hidden"
  >
    <div class="p-4">
      <p class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Choose Theme</p>
      
      <!-- Theme Options Grid -->
      <div class="grid grid-cols-2 gap-3">
        <!-- Light Theme -->
        <button
          class="theme-option relative flex flex-col items-center gap-2 p-3 rounded-xl border-2 border-gray-200 hover:border-blue-500 transition-all"
          data-theme="light"
          onclick="selectTheme(this)"
        >
          <div class="w-full h-16 rounded-lg bg-white border border-gray-200 flex items-center justify-center">
            <svg class="w-8 h-8 text-amber-500" fill="currentColor" viewBox="0 0 24 24">
              <path d="M12 2.25a.75.75 0 01.75.75v2.25a.75.75 0 01-1.5 0V3a.75.75 0 01.75-.75zM7.5 12a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM18.894 6.166a.75.75 0 00-1.06-1.06l-1.591 1.59a.75.75 0 101.06 1.061l1.591-1.59zM21.75 12a.75.75 0 01-.75.75h-2.25a.75.75 0 010-1.5H21a.75.75 0 01.75.75zM17.834 18.894a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 10-1.061 1.06l1.59 1.591zM12 18a.75.75 0 01.75.75V21a.75.75 0 01-1.5 0v-2.25A.75.75 0 0112 18zM7.758 17.303a.75.75 0 00-1.061-1.06l-1.591 1.59a.75.75 0 001.06 1.061l1.591-1.59zM6 12a.75.75 0 01-.75.75H3a.75.75 0 010-1.5h2.25A.75.75 0 016 12zM6.697 7.757a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 00-1.061 1.06l1.59 1.591z"></path>
            </svg>
          </div>
          <span class="text-sm font-medium text-gray-700">Light</span>
          <svg class="absolute top-2 right-2 w-5 h-5 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
          </svg>
        </button>

        <!-- Dark Theme -->
        <button
          class="theme-option relative flex flex-col items-center gap-2 p-3 rounded-xl border-2 border-gray-200 hover:border-blue-500 transition-all"
          data-theme="dark"
          onclick="selectTheme(this)"
        >
          <div class="w-full h-16 rounded-lg bg-slate-800 flex items-center justify-center">
            <svg class="w-8 h-8 text-slate-200" fill="currentColor" viewBox="0 0 24 24">
              <path fill-rule="evenodd" d="M9.528 1.718a.75.75 0 01.162.819A8.97 8.97 0 009 6a9 9 0 009 9 8.97 8.97 0 003.463-.69.75.75 0 01.981.98 10.503 10.503 0 01-9.694 6.46c-5.799 0-10.5-4.701-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 01.818.162z" clip-rule="evenodd"></path>
            </svg>
          </div>
          <span class="text-sm font-medium text-gray-700">Dark</span>
          <svg class="absolute top-2 right-2 w-5 h-5 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
          </svg>
        </button>

        <!-- System Theme -->
        <button
          class="theme-option relative flex flex-col items-center gap-2 p-3 rounded-xl border-2 border-gray-200 hover:border-blue-500 transition-all"
          data-theme="system"
          onclick="selectTheme(this)"
        >
          <div class="w-full h-16 rounded-lg bg-gradient-to-br from-white to-slate-800 flex items-center justify-center">
            <svg class="w-8 h-8 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
            </svg>
          </div>
          <span class="text-sm font-medium text-gray-700">System</span>
          <svg class="absolute top-2 right-2 w-5 h-5 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
          </svg>
        </button>

        <!-- Sepia Theme -->
        <button
          class="theme-option relative flex flex-col items-center gap-2 p-3 rounded-xl border-2 border-gray-200 hover:border-blue-500 transition-all"
          data-theme="sepia"
          onclick="selectTheme(this)"
        >
          <div class="w-full h-16 rounded-lg bg-amber-50 border border-amber-200 flex items-center justify-center">
            <svg class="w-8 h-8 text-amber-700" fill="currentColor" viewBox="0 0 24 24">
              <path d="M6 2a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V4a2 2 0 00-2-2H6z"></path>
            </svg>
          </div>
          <span class="text-sm font-medium text-gray-700">Sepia</span>
          <svg class="absolute top-2 right-2 w-5 h-5 text-blue-600 hidden check-icon" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
          </svg>
        </button>
      </div>
    </div>

    <!-- Accent Colors -->
    <div class="px-4 pb-4">
      <p class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Accent Color</p>
      <div class="flex gap-2">
        <button class="accent-option w-8 h-8 rounded-full bg-blue-600 ring-2 ring-offset-2 ring-blue-600 hover:scale-110 transition-transform" onclick="setAccentColor('blue')"></button>
        <button class="accent-option w-8 h-8 rounded-full bg-purple-600 ring-2 ring-offset-2 ring-transparent hover:ring-purple-600 hover:scale-110 transition-transform" onclick="setAccentColor('purple')"></button>
        <button class="accent-option w-8 h-8 rounded-full bg-pink-600 ring-2 ring-offset-2 ring-transparent hover:ring-pink-600 hover:scale-110 transition-transform" onclick="setAccentColor('pink')"></button>
        <button class="accent-option w-8 h-8 rounded-full bg-emerald-600 ring-2 ring-offset-2 ring-transparent hover:ring-emerald-600 hover:scale-110 transition-transform" onclick="setAccentColor('emerald')"></button>
        <button class="accent-option w-8 h-8 rounded-full bg-amber-600 ring-2 ring-offset-2 ring-transparent hover:ring-amber-600 hover:scale-110 transition-transform" onclick="setAccentColor('amber')"></button>
        <button class="accent-option w-8 h-8 rounded-full bg-red-600 ring-2 ring-offset-2 ring-transparent hover:ring-red-600 hover:scale-110 transition-transform" onclick="setAccentColor('red')"></button>
      </div>
    </div>
  </div>
</div>

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

  function selectTheme(element) {
    document.querySelectorAll('.theme-option').forEach(opt => {
      opt.classList.remove('border-blue-500', 'bg-blue-50');
      opt.classList.add('border-gray-200');
      opt.querySelector('.check-icon').classList.add('hidden');
    });
    
    element.classList.remove('border-gray-200');
    element.classList.add('border-blue-500', 'bg-blue-50');
    element.querySelector('.check-icon').classList.remove('hidden');
    
    // Toggle dropdown close
    // toggleDropdown('theme-menu');
  }

  function setAccentColor(color) {
    document.querySelectorAll('.accent-option').forEach(btn => {
      btn.classList.remove('ring-blue-600', 'ring-purple-600', 'ring-pink-600', 'ring-emerald-600', 'ring-amber-600', 'ring-red-600');
      btn.classList.add('ring-transparent');
    });
    
    event.target.classList.remove('ring-transparent');
    event.target.classList.add(`ring-${color}-600`);
  }

  document.addEventListener('click', function(event) {
    const container = document.querySelector('.relative.inline-block');
    if (!container.contains(event.target)) {
      document.getElementById('theme-menu').classList.add('hidden');
    }
  });
</script>
147 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/theme-switcher
Prompt instruction
I want to use this DevSnips resource in production:

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

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

This is the Theme Switcher — Theme switcher dropdown with light, dark, system, and sepia themes plus accent color selection.

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/theme-switcher