Component

Tabs

Complete tab component family with 15 production-ready variants covering documentation, dashboards, settings, mobile navigation, and animated indicators.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Tabs
registry path: Tailwind/Components/Tabs

Source

Implementation

code.html
<div class="w-full max-w-3xl">
  <div class="relative">
    <div role="tablist" aria-label="Project workspace" class="flex items-center gap-6 border-b border-gray-200">
      <button role="tab" id="atab-board" aria-selected="true" aria-controls="apanel-board" tabindex="0"
        class="relative pb-3 text-sm font-medium text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 rounded whitespace-nowrap">
        Board
      </button>
      <button role="tab" id="atab-timeline" aria-selected="false" aria-controls="apanel-timeline" tabindex="-1"
        class="relative pb-3 text-sm font-medium text-gray-500 hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 rounded whitespace-nowrap">
        Timeline
      </button>
      <button role="tab" id="atab-calendar" aria-selected="false" aria-controls="apanel-calendar" tabindex="-1"
        class="relative pb-3 text-sm font-medium text-gray-500 hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 rounded whitespace-nowrap">
        Calendar
      </button>
      <button role="tab" id="atab-files" aria-selected="false" aria-controls="apanel-files" tabindex="-1"
        class="relative pb-3 text-sm font-medium text-gray-500 hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500 rounded whitespace-nowrap">
        Files
      </button>
      <span class="a-indicator absolute bottom-0 h-0.5 bg-rose-500 rounded-full transition-all duration-300 ease-out" aria-hidden="true"></span>
    </div>
  </div>

  <div class="mt-6">
    <div role="tabpanel" id="apanel-board" aria-labelledby="atab-board" tabindex="0" class="grid grid-cols-3 gap-3 focus:outline-none">
      <div class="rounded-xl bg-gray-50 border border-gray-200 p-3"><p class="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">To do</p><div class="rounded-lg bg-white border border-gray-200 p-3"><p class="text-sm font-medium text-gray-900">Design review</p><p class="text-xs text-gray-500 mt-1">Due Aug 6</p></div></div>
      <div class="rounded-xl bg-gray-50 border border-gray-200 p-3"><p class="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">In progress</p><div class="rounded-lg bg-white border border-gray-200 p-3"><p class="text-sm font-medium text-gray-900">API integration</p><p class="text-xs text-gray-500 mt-1">Due Aug 8</p></div></div>
      <div class="rounded-xl bg-gray-50 border border-gray-200 p-3"><p class="text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2">Done</p><div class="rounded-lg bg-white border border-gray-200 p-3"><p class="text-sm font-medium text-gray-900">User research</p><p class="text-xs text-emerald-600 mt-1">Completed</p></div></div>
    </div>
    <div role="tabpanel" id="apanel-timeline" aria-labelledby="atab-timeline" tabindex="0" class="hidden focus:outline-none">
      <ol class="relative border-l border-gray-200 ml-3 space-y-5">
        <li class="ml-4"><span class="absolute -left-[5px] w-2.5 h-2.5 bg-rose-500 rounded-full"></span><p class="text-sm font-medium text-gray-900">Project kickoff</p><p class="text-xs text-gray-500">Aug 1</p></li>
        <li class="ml-4"><span class="absolute -left-[5px] w-2.5 h-2.5 bg-gray-300 rounded-full"></span><p class="text-sm font-medium text-gray-900">Design sprint</p><p class="text-xs text-gray-500">Aug 3 — Aug 5</p></li>
        <li class="ml-4"><span class="absolute -left-[5px] w-2.5 h-2.5 bg-gray-300 rounded-full"></span><p class="text-sm font-medium text-gray-900">Launch</p><p class="text-xs text-gray-500">Aug 15</p></li>
      </ol>
    </div>
    <div role="tabpanel" id="apanel-calendar" aria-labelledby="atab-calendar" tabindex="0" class="hidden focus:outline-none">
      <div class="grid grid-cols-7 gap-1 text-center text-xs">
        <div class="text-gray-400 font-medium py-1">M</div><div class="text-gray-400 font-medium py-1">T</div><div class="text-gray-400 font-medium py-1">W</div><div class="text-gray-400 font-medium py-1">T</div><div class="text-gray-400 font-medium py-1">F</div><div class="text-gray-400 font-medium py-1">S</div><div class="text-gray-400 font-medium py-1">S</div>
        <div class="py-2 rounded bg-rose-50 text-rose-700 font-semibold">4</div><div class="py-2 rounded hover:bg-gray-100">5</div><div class="py-2 rounded hover:bg-gray-100">6</div><div class="py-2 rounded hover:bg-gray-100">7</div><div class="py-2 rounded hover:bg-gray-100">8</div><div class="py-2 rounded hover:bg-gray-100">9</div><div class="py-2 rounded hover:bg-gray-100">10</div>
      </div>
    </div>
    <div role="tabpanel" id="apanel-files" aria-labelledby="atab-files" tabindex="0" class="hidden focus:outline-none">
      <div class="divide-y divide-gray-100 rounded-xl border border-gray-200">
        <div class="flex items-center gap-3 p-3"><span class="w-8 h-8 rounded-lg bg-rose-50 text-rose-600 flex items-center justify-center"><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="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/></svg></span><div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">spec-v2.pdf</p><p class="text-xs text-gray-500">2.4 MB</p></div></div>
        <div class="flex items-center gap-3 p-3"><span class="w-8 h-8 rounded-lg bg-rose-50 text-rose-600 flex items-center justify-center"><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="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg></span><div class="min-w-0 flex-1"><p class="text-sm font-medium text-gray-900 truncate">mockups.png</p><p class="text-xs text-gray-500">840 KB</p></div></div>
      </div>
    </div>
  </div>
</div>

<script>
  (function () {
    var list = document.querySelector('[aria-label="Project workspace"]');
    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')); });
    var indicator = list.querySelector('.a-indicator');
    function moveIndicator(tab) {
      if (!indicator) return;
      indicator.style.left = tab.offsetLeft + 'px';
      indicator.style.width = tab.offsetWidth + 'px';
    }
    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-gray-900', s); t.classList.toggle('text-gray-500', !s);
      });
      moveIndicator(tab);
      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 (e.key === 'Home') idx = 0;
        if (e.key === 'End') idx = tabs.length - 1;
        if (idx !== null) { e.preventDefault(); tabs[idx].focus(); activate(tabs[idx]); }
      });
    });
    moveIndicator(tabs[0]);
    window.addEventListener('resize', function () {
      var active = list.querySelector('[aria-selected="true"]') || tabs[0];
      moveIndicator(active);
    });
  })();
</script>
92 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

Continue browsing

View all