Component

Pill Tabs

SaaS dashboard pill tabs with count badges for customer segments. Filled active pill, outlined inactive pills, and a contextual action toolbar.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Tabs/pill-tabs
registry path: Tailwind/Components/Tabs/pill-tabs

Source

Implementation

code.html
<div class="w-full max-w-4xl">
  <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
    <div>
      <h2 class="text-xl font-semibold text-gray-900">Customers</h2>
      <p class="text-sm text-gray-500">Manage your contacts, leads, and active accounts</p>
    </div>
    <div class="flex items-center gap-2">
      <button class="inline-flex items-center gap-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg px-3 py-2 hover:bg-gray-50 transition-colors">
        <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="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"/></svg>
        Filter
      </button>
      <button class="inline-flex items-center gap-2 text-sm font-medium text-white bg-indigo-600 rounded-lg px-3 py-2 hover:bg-indigo-700 transition-colors">
        <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="M12 4v16m8-8H4"/></svg>
        Add
      </button>
    </div>
  </div>

  <div role="tablist" aria-label="Customer segments" class="flex flex-wrap items-center gap-2">
    <button role="tab" id="ptab-all" aria-selected="true" aria-controls="ppanel-all" tabindex="0"
      class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-full transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2">
      All customers
      <span class="text-xs font-semibold text-indigo-100 bg-indigo-500 px-2 py-0.5 rounded-full">1,284</span>
    </button>
    <button role="tab" id="ptab-leads" aria-selected="false" aria-controls="ppanel-leads" tabindex="-1"
      class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-full hover:bg-gray-50 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2">
      Leads
      <span class="text-xs font-semibold text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full">412</span>
    </button>
    <button role="tab" id="ptab-active" aria-selected="false" aria-controls="ppanel-active" tabindex="-1"
      class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-full hover:bg-gray-50 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2">
      Active
      <span class="text-xs font-semibold text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full">738</span>
    </button>
    <button role="tab" id="ptab-churned" aria-selected="false" aria-controls="ppanel-churned" tabindex="-1"
      class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-full hover:bg-gray-50 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2">
      Churned
      <span class="text-xs font-semibold text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full">134</span>
    </button>
  </div>

  <div class="mt-4 bg-white rounded-xl border border-gray-200 divide-y divide-gray-100">
    <div role="tabpanel" id="ppanel-all" aria-labelledby="ptab-all" tabindex="0" class="focus:outline-none">
      <div class="flex items-center gap-3 p-4">
        <img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop&crop=faces" alt="" class="w-9 h-9 rounded-full object-cover">
        <div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">Sarah Mitchell</p><p class="text-xs text-gray-500 truncate">sarah@acme.io · Pro plan</p></div>
        <span class="text-xs font-medium text-emerald-700 bg-emerald-50 px-2 py-1 rounded-full">Active</span>
      </div>
      <div class="flex items-center gap-3 p-4">
        <img src="https://images.unsplash.com/photo-1500648767791-00dcc664cbcb?w=40&h=40&fit=crop&crop=faces" alt="" class="w-9 h-9 rounded-full object-cover">
        <div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">James Rivera</p><p class="text-xs text-gray-500 truncate">james@nimbus.co · Team plan</p></div>
        <span class="text-xs font-medium text-amber-700 bg-amber-50 px-2 py-1 rounded-full">Lead</span>
      </div>
    </div>
    <div role="tabpanel" id="ppanel-leads" aria-labelledby="ptab-leads" tabindex="0" class="hidden focus:outline-none">
      <div class="flex items-center gap-3 p-4">
        <img src="https://images.unsplash.com/photo-1500648767791-00dcc664cbcb?w=40&h=40&fit=crop&crop=faces" alt="" class="w-9 h-9 rounded-full object-cover">
        <div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">James Rivera</p><p class="text-xs text-gray-500 truncate">james@nimbus.co · Trial</p></div>
        <span class="text-xs font-medium text-amber-700 bg-amber-50 px-2 py-1 rounded-full">Lead</span>
      </div>
    </div>
    <div role="tabpanel" id="ppanel-active" aria-labelledby="ptab-active" tabindex="0" class="hidden focus:outline-none">
      <div class="flex items-center gap-3 p-4">
        <img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop&crop=faces" alt="" class="w-9 h-9 rounded-full object-cover">
        <div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">Sarah Mitchell</p><p class="text-xs text-gray-500 truncate">sarah@acme.io · Pro plan</p></div>
        <span class="text-xs font-medium text-emerald-700 bg-emerald-50 px-2 py-1 rounded-full">Active</span>
      </div>
    </div>
    <div role="tabpanel" id="ppanel-churned" aria-labelledby="ptab-churned" tabindex="0" class="hidden focus:outline-none">
      <div class="flex items-center gap-3 p-4">
        <img src="https://images.unsplash.com/photo-1438761681033-6461ffad8d35?w=40&h=40&fit=crop&crop=faces" alt="" class="w-9 h-9 rounded-full object-cover">
        <div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">Dana Pierce</p><p class="text-xs text-gray-500 truncate">dana@oldco.com · Cancelled</p></div>
        <span class="text-xs font-medium text-rose-700 bg-rose-50 px-2 py-1 rounded-full">Churned</span>
      </div>
    </div>
  </div>
</div>

<script>
  (function () {
    var list = document.querySelector('[aria-label="Customer segments"]');
    if (!list) return;
    var tabs = Array.prototype.slice.call(list.querySelectorAll('[role="tab"]'));
    var panels = tabs.map(function (t) { return document.getElementById(t.getAttribute('aria-controls')); });
    function activate(tab) {
      tabs.forEach(function (t) {
        var s = t === tab;
        t.setAttribute('aria-selected', s); t.tabIndex = s ? 0 : -1;
        t.classList.toggle('text-white', s); t.classList.toggle('bg-indigo-600', s);
        t.classList.toggle('text-gray-700', !s); t.classList.toggle('bg-white', !s); t.classList.toggle('border', !s); t.classList.toggle('border-gray-300', !s); t.classList.toggle('hover:bg-gray-50', !s);
      });
      panels.forEach(function (p) { if (p) p.classList.add('hidden'); });
      var panel = document.getElementById(tab.getAttribute('aria-controls'));
      if (panel) panel.classList.remove('hidden');
    }
    tabs.forEach(function (tab, i) {
      tab.addEventListener('click', function () { activate(tab); });
      tab.addEventListener('keydown', function (e) {
        var idx = null;
        if (e.key === 'ArrowRight') idx = (i + 1) % tabs.length;
        if (e.key === 'ArrowLeft') idx = (i - 1 + tabs.length) % tabs.length;
        if (idx !== null) { e.preventDefault(); tabs[idx].focus(); activate(tabs[idx]); }
      });
    });
  })();
</script>
106 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/tabs/pill-tabs

Continue browsing

View all