Component
Searchable Select
Searchable dropdown with real-time filtering, country flags, and no-results state for large lists.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.dev/library/tailwind/components/dropdowns/searchable-select/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Dropdowns/searchable-select Tailwind/Components/Dropdowns/searchable-select <!-- Searchable Select -->
<div class="relative" id="searchable-container">
<label class="block text-sm font-medium text-gray-700 mb-2">Search Country</label>
<div
id="searchable-trigger"
class="relative w-full px-4 py-3 text-left bg-white border border-gray-300 rounded-lg cursor-pointer hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
onclick="toggleSearchable('searchable-menu')"
>
<div class="flex items-center justify-between">
<div id="selected-country" class="flex items-center gap-3">
<span class="text-gray-400">Type to search...</span>
</div>
<svg class="w-5 h-5 text-gray-400 transition-transform" id="searchable-arrow" 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>
</div>
</div>
<!-- Search Input (inside dropdown) -->
<div
id="searchable-menu"
class="hidden absolute z-10 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden"
>
<div class="p-2 border-b border-gray-100">
<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"
id="search-input"
class="w-full pl-10 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"
placeholder="Search countries..."
oninput="filterCountries()"
/>
</div>
</div>
<!-- Results -->
<ul id="country-list" class="py-2 max-h-64 overflow-auto">
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="United States"
onclick="selectCountry(this)"
>
<span class="text-xl">🇺🇸</span>
<div>
<p class="font-medium">United States</p>
<p class="text-xs text-gray-500">North America</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="United Kingdom"
onclick="selectCountry(this)"
>
<span class="text-xl">🇬🇧</span>
<div>
<p class="font-medium">United Kingdom</p>
<p class="text-xs text-gray-500">Europe</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="Germany"
onclick="selectCountry(this)"
>
<span class="text-xl">🇩🇪</span>
<div>
<p class="font-medium">Germany</p>
<p class="text-xs text-gray-500">Europe</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="France"
onclick="selectCountry(this)"
>
<span class="text-xl">🇫🇷</span>
<div>
<p class="font-medium">France</p>
<p class="text-xs text-gray-500">Europe</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="Japan"
onclick="selectCountry(this)"
>
<span class="text-xl">🇯🇵</span>
<div>
<p class="font-medium">Japan</p>
<p class="text-xs text-gray-500">Asia</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="Australia"
onclick="selectCountry(this)"
>
<span class="text-xl">🇦🇺</span>
<div>
<p class="font-medium">Australia</p>
<p class="text-xs text-gray-500">Oceania</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="Brazil"
onclick="selectCountry(this)"
>
<span class="text-xl">🇧🇷</span>
<div>
<p class="font-medium">Brazil</p>
<p class="text-xs text-gray-500">South America</p>
</div>
</li>
<li
class="country-option px-4 py-2.5 text-gray-700 cursor-pointer hover:bg-blue-50 hover:text-blue-600 transition-colors flex items-center gap-3"
data-country="Canada"
onclick="selectCountry(this)"
>
<span class="text-xl">🇨🇦</span>
<div>
<p class="font-medium">Canada</p>
<p class="text-xs text-gray-500">North America</p>
</div>
</li>
</ul>
<!-- No Results -->
<div id="no-results" class="hidden py-8 text-center">
<svg class="w-12 h-12 text-gray-300 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<p class="text-gray-500">No countries found</p>
</div>
</div>
</div>
<script>
function toggleSearchable(id) {
const menu = document.getElementById(id);
const arrow = document.getElementById('searchable-arrow');
menu.classList.toggle('hidden');
arrow.classList.toggle('rotate-180');
if (!menu.classList.contains('hidden')) {
document.getElementById('search-input').focus();
}
}
function filterCountries() {
const input = document.getElementById('search-input').value.toLowerCase();
const options = document.querySelectorAll('.country-option');
let hasResults = false;
options.forEach(option => {
const country = option.getAttribute('data-country').toLowerCase();
if (country.includes(input)) {
option.classList.remove('hidden');
hasResults = true;
} else {
option.classList.add('hidden');
}
});
document.getElementById('no-results').classList.toggle('hidden', hasResults);
}
function selectCountry(element) {
const country = element.getAttribute('data-country');
const selectedDisplay = document.getElementById('selected-country');
selectedDisplay.innerHTML = element.innerHTML;
selectedDisplay.classList.remove('text-gray-400');
document.querySelectorAll('.country-option').forEach(opt => {
opt.classList.remove('bg-blue-50', 'text-blue-600');
});
element.classList.add('bg-blue-50', 'text-blue-600');
toggleSearchable('searchable-menu');
}
document.addEventListener('click', function(event) {
const container = document.getElementById('searchable-container');
if (!container.contains(event.target)) {
document.getElementById('searchable-menu').classList.add('hidden');
document.getElementById('searchable-arrow').classList.remove('rotate-180');
}
});
</script> # Searchable Select
Searchable select dropdown.
## Preview
Open `preview.html` for a standalone demonstration.
## Features
- Search input + filtered options
## Usage
```bash
npx devsnips add Tailwind/Components/Dropdowns/searchable-select
```
Copy from `code.html`.
## Customization
- Input and list styles
## Accessibility
- Label the combobox/input; manage active option state
## Dependencies
- Tailwind CSS; JS for filtering as present
## File Structure
- `code.html` · `preview.html` · `metadata.json` · `README.md` 201 lines UTF-8 · LF · Spaces: 2
Continue browsing