Component

Multi Open Accordion

Faceted filter panel where multiple sections stay open at once. Each section holds checkbox filters with a live selected-count badge for e-commerce and directory filtering.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Accordions/multi-open-accordion
registry path: Tailwind/Components/Accordions/multi-open-accordion

Source

Implementation

code.html
<!--
Snippet Name: Multi Open Accordion
Description: Faceted filter panel. Multiple sections expand independently and stay open, each holding checkbox filters with a selected-count badge.
Author: DevSnips Contributors
Usage Example: E-commerce or directory filters where users compare options across categories.
-->
<div class="space-y-2.5" data-accordion="multi">
  <div class="overflow-hidden rounded-xl border border-gray-200 bg-white" data-accordion-item>
    <h3>
      <button type="button" id="multi-trigger-1" aria-controls="multi-panel-1" aria-expanded="true" class="accordion-trigger group flex w-full items-center justify-between gap-3 px-4 py-3 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-inset rounded-xl">
        <span class="flex items-center gap-2"><span class="text-sm font-semibold text-gray-900">Category</span><span data-count class="rounded-full bg-indigo-100 px-2 py-0.5 text-[11px] font-medium text-indigo-700">2</span></span>
        <svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" style="transform: rotate(180deg)" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
      </button>
    </h3>
    <div id="multi-panel-1" role="region" aria-labelledby="multi-trigger-1" class="accordion-panel grid grid-rows-[1fr] transition-[grid-template-rows] duration-300 ease-out">
      <div class="overflow-hidden">
        <fieldset class="border-t border-gray-100 px-4 py-3">
          <legend class="sr-only">Filter by category</legend>
          <div class="space-y-2.5">
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" checked> Components</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" checked> Pages</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> Sections</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> Templates</label>
          </div>
        </fieldset>
      </div>
    </div>
  </div>

  <div class="overflow-hidden rounded-xl border border-gray-200 bg-white" data-accordion-item>
    <h3>
      <button type="button" id="multi-trigger-2" aria-controls="multi-panel-2" aria-expanded="true" class="accordion-trigger group flex w-full items-center justify-between gap-3 px-4 py-3 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-inset rounded-xl">
        <span class="flex items-center gap-2"><span class="text-sm font-semibold text-gray-900">Framework</span><span data-count class="rounded-full bg-indigo-100 px-2 py-0.5 text-[11px] font-medium text-indigo-700">1</span></span>
        <svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" style="transform: rotate(180deg)" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
      </button>
    </h3>
    <div id="multi-panel-2" role="region" aria-labelledby="multi-trigger-2" class="accordion-panel grid grid-rows-[1fr] transition-[grid-template-rows] duration-300 ease-out">
      <div class="overflow-hidden">
        <fieldset class="border-t border-gray-100 px-4 py-3">
          <legend class="sr-only">Filter by framework</legend>
          <div class="space-y-2.5">
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" checked> Tailwind CSS</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> Vanilla HTML/CSS</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> React</label>
          </div>
        </fieldset>
      </div>
    </div>
  </div>

  <div class="overflow-hidden rounded-xl border border-gray-200 bg-white" data-accordion-item>
    <h3>
      <button type="button" id="multi-trigger-3" aria-controls="multi-panel-3" aria-expanded="false" class="accordion-trigger group flex w-full items-center justify-between gap-3 px-4 py-3 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-inset rounded-xl">
        <span class="flex items-center gap-2"><span class="text-sm font-semibold text-gray-900">License</span><span data-count class="rounded-full bg-indigo-100 px-2 py-0.5 text-[11px] font-medium text-indigo-700">0</span></span>
        <svg class="accordion-chevron h-5 w-5 shrink-0 text-gray-400 transition-transform duration-300 ease-out" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
      </button>
    </h3>
    <div id="multi-panel-3" role="region" aria-labelledby="multi-trigger-3" class="accordion-panel grid grid-rows-[0fr] transition-[grid-template-rows] duration-300 ease-out">
      <div class="overflow-hidden">
        <fieldset class="border-t border-gray-100 px-4 py-3">
          <legend class="sr-only">Filter by license</legend>
          <div class="space-y-2.5">
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> MIT</label>
            <label class="flex cursor-pointer items-center gap-2.5 text-sm text-gray-700"><input type="checkbox" class="multi-check h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> Apache 2.0</label>
          </div>
        </fieldset>
      </div>
    </div>
  </div>

  <script>
    (function () {
      const root = document.currentScript.closest('[data-accordion]');
      if (!root) return;
      root.querySelectorAll('[data-accordion-item]').forEach((item) => {
        const trigger = item.querySelector('.accordion-trigger');
        const panel = item.querySelector('.accordion-panel');
        const chevron = item.querySelector('.accordion-chevron');
        const count = item.querySelector('[data-count]');
        const checks = item.querySelectorAll('.multi-check');
        if (!trigger || !panel) return;
        const syncCount = () => { if (count) count.textContent = Array.from(checks).filter((c) => c.checked).length; };
        const toggle = () => {
          const open = trigger.getAttribute('aria-expanded') === 'true';
          trigger.setAttribute('aria-expanded', String(!open));
          panel.classList.toggle('grid-rows-[1fr]', !open);
          panel.classList.toggle('grid-rows-[0fr]', open);
          if (chevron) chevron.style.transform = open ? '' : 'rotate(180deg)';
        };
        trigger.addEventListener('click', toggle);
        checks.forEach((c) => c.addEventListener('change', syncCount));
        syncCount();
      });
    })();
  </script>
</div>
96 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/accordions/multi-open-accordion

Continue browsing

View all