Component

Multi Select

Multi-select dropdown with checkboxes, technology badges, and removable tags for multiple selections.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Dropdowns/multi-select
registry path: Tailwind/Components/Dropdowns/multi-select

Source

Implementation

code.html
<!-- Multi Select -->
<div class="relative" id="multi-select-container">
  <label class="block text-sm font-medium text-gray-700 mb-2">Select Technologies</label>
  
  <!-- Multi Select Trigger -->
  <div
    id="multi-select-trigger"
    class="relative w-full min-h-[52px] px-3 py-2 bg-white border border-gray-300 rounded-lg cursor-pointer hover:border-gray-400 focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500 transition-colors"
    onclick="toggleMultiSelect('multi-select-menu')"
  >
    <!-- Selected Tags -->
    <div id="selected-tags" class="flex flex-wrap gap-2">
      <span class="text-gray-400 text-sm">Select technologies...</span>
    </div>
  </div>

  <!-- Multi Select Menu -->
  <div
    id="multi-select-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-3 border-b border-gray-100 bg-gray-50">
      <p class="text-xs font-medium text-gray-500">Select one or more options</p>
    </div>

    <div class="py-2 max-h-64 overflow-auto">
      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="react"
          data-label="React"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-cyan-100 flex items-center justify-center">
            <span class="text-xs">⚛️</span>
          </span>
          <span class="text-sm text-gray-700">React</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="vue"
          data-label="Vue.js"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-green-100 flex items-center justify-center">
            <span class="text-xs">💚</span>
          </span>
          <span class="text-sm text-gray-700">Vue.js</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="angular"
          data-label="Angular"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-red-100 flex items-center justify-center">
            <span class="text-xs">🔴</span>
          </span>
          <span class="text-sm text-gray-700">Angular</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="node"
          data-label="Node.js"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-green-100 flex items-center justify-center">
            <span class="text-xs">🟢</span>
          </span>
          <span class="text-sm text-gray-700">Node.js</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="python"
          data-label="Python"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-yellow-100 flex items-center justify-center">
            <span class="text-xs">🐍</span>
          </span>
          <span class="text-sm text-gray-700">Python</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="typescript"
          data-label="TypeScript"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-blue-100 flex items-center justify-center">
            <span class="text-xs">TS</span>
          </span>
          <span class="text-sm text-gray-700">TypeScript</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="go"
          data-label="Go"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-cyan-100 flex items-center justify-center">
            <span class="text-xs">🔵</span>
          </span>
          <span class="text-sm text-gray-700">Go</span>
        </div>
      </label>

      <label class="flex items-center gap-3 px-4 py-2.5 hover:bg-blue-50 cursor-pointer transition-colors">
        <input
          type="checkbox"
          class="tech-checkbox w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
          data-value="rust"
          data-label="Rust"
          onchange="updateMultiSelect()"
        />
        <div class="flex items-center gap-2">
          <span class="w-6 h-6 rounded bg-orange-100 flex items-center justify-center">
            <span class="text-xs">🦀</span>
          </span>
          <span class="text-sm text-gray-700">Rust</span>
        </div>
      </label>
    </div>

    <!-- Footer -->
    <div class="px-4 py-3 border-t border-gray-100 bg-gray-50 flex items-center justify-between">
      <span id="selection-count" class="text-xs text-gray-500">0 selected</span>
      <button
        type="button"
        class="text-xs font-medium text-blue-600 hover:text-blue-700"
        onclick="clearMultiSelect()"
      >
        Clear all
      </button>
    </div>
  </div>
</div>

<script>
  function toggleMultiSelect(id) {
    const menu = document.getElementById(id);
    menu.classList.toggle('hidden');
  }

  function updateMultiSelect() {
    const checkboxes = document.querySelectorAll('.tech-checkbox:checked');
    const selectedContainer = document.getElementById('selected-tags');
    const selectionCount = document.getElementById('selection-count');
    
    if (checkboxes.length === 0) {
      selectedContainer.innerHTML = '<span class="text-gray-400 text-sm">Select technologies...</span>';
    } else {
      selectedContainer.innerHTML = Array.from(checkboxes).map(cb => {
        const label = cb.getAttribute('data-label');
        const value = cb.getAttribute('data-value');
        return `
          <span class="inline-flex items-center gap-1 px-2.5 py-1 bg-blue-100 text-blue-700 text-sm rounded-lg">
            ${label}
            <button type="button" onclick="removeTag('${value}')" class="hover:text-blue-900">
              <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
              </svg>
            </button>
          </span>
        `;
      }).join('');
    }
    
    selectionCount.textContent = `${checkboxes.length} selected`;
  }

  function removeTag(value) {
    const checkbox = document.querySelector(`.tech-checkbox[data-value="${value}"]`);
    if (checkbox) {
      checkbox.checked = false;
      updateMultiSelect();
    }
  }

  function clearMultiSelect() {
    document.querySelectorAll('.tech-checkbox').forEach(cb => {
      cb.checked = false;
    });
    updateMultiSelect();
  }

  document.addEventListener('click', function(event) {
    const container = document.getElementById('multi-select-container');
    if (!container.contains(event.target)) {
      document.getElementById('multi-select-menu').classList.add('hidden');
    }
  });
</script>
224 lines UTF-8 · LF · Spaces: 2

AI-ready

Available to your agent.

This component is reachable through the DevSnips CLI, MCP server and Skills integrations — one registry, one resource path.

Resource path

devsnips://components/dropdowns/multi-select

Continue browsing

View all