Component
Theme Switcher
Theme switcher dropdown with light, dark, system, and sepia themes plus accent color selection.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.site/library/tailwind/components/dropdowns/theme-switcher/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Dropdowns/theme-switcher Tailwind/Components/Dropdowns/theme-switcher <!-- 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> # Theme Switcher
Theme selection dropdown (light/dark/system, etc.).
## Preview
Open `preview.html` for a standalone demonstration.
## Features
- Theme options
- Current selection presentation
## Usage
```bash
npx devsnips add Tailwind/Components/Dropdowns/theme-switcher
```
Copy from `code.html`. Wire selection to your theme system.
## Customization
- Option icons/labels, trigger styles
## Accessibility
- Expose the current theme accessibly
## Dependencies
- Tailwind CSS; JS as present
## File Structure
- `code.html` · `preview.html` · `metadata.json` · `README.md` 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 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