Component

Bordered Tabs

Bordered enterprise tab set with a connected content panel, status badges, and data tables. Designed for dense operational dashboards like order and inventory management.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

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

Install

Add to your project

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

Source

Implementation

code.html
<div class="w-full max-w-5xl">
  <div role="tablist" aria-label="Operations" class="flex flex-wrap items-center gap-px bg-gray-200 rounded-lg overflow-hidden border border-gray-200">
    <button role="tab" id="btab-overview" aria-selected="true" aria-controls="bpanel-overview" tabindex="0"
      class="flex-1 min-w-[120px] px-4 py-3 text-sm font-medium text-blue-700 bg-white border-b-2 border-blue-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500">
      Overview
    </button>
    <button role="tab" id="btab-orders" aria-selected="false" aria-controls="bpanel-orders" tabindex="-1"
      class="flex-1 min-w-[120px] px-4 py-3 text-sm font-medium text-gray-600 bg-gray-50 border-b-2 border-transparent hover:bg-white hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500">
      Orders <span class="ml-1 text-xs font-semibold text-gray-500 bg-gray-200 px-1.5 py-0.5 rounded">28</span>
    </button>
    <button role="tab" id="btab-inventory" aria-selected="false" aria-controls="bpanel-inventory" tabindex="-1"
      class="flex-1 min-w-[120px] px-4 py-3 text-sm font-medium text-gray-600 bg-gray-50 border-b-2 border-transparent hover:bg-white hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500">
      Inventory
    </button>
    <button role="tab" id="btab-reports" aria-selected="false" aria-controls="bpanel-reports" tabindex="-1"
      class="flex-1 min-w-[120px] px-4 py-3 text-sm font-medium text-gray-600 bg-gray-50 border-b-2 border-transparent hover:bg-white hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500">
      Reports
    </button>
    <button role="tab" id="btab-audit" aria-selected="false" aria-controls="bpanel-audit" tabindex="-1"
      class="flex-1 min-w-[120px] px-4 py-3 text-sm font-medium text-gray-600 bg-gray-50 border-b-2 border-transparent hover:bg-white hover:text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500">
      Audit log
    </button>
  </div>

  <div class="mt-px bg-white border border-t-0 border-gray-200 rounded-b-lg p-6">
    <div role="tabpanel" id="bpanel-overview" aria-labelledby="btab-overview" tabindex="0" class="focus:outline-none">
      <div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <div class="border border-gray-200 rounded-lg p-4"><p class="text-xs font-medium text-gray-500 uppercase tracking-wide">Open orders</p><p class="mt-1 text-2xl font-bold text-gray-900">28</p></div>
        <div class="border border-gray-200 rounded-lg p-4"><p class="text-xs font-medium text-gray-500 uppercase tracking-wide">Low stock</p><p class="mt-1 text-2xl font-bold text-amber-600">7</p></div>
        <div class="border border-gray-200 rounded-lg p-4"><p class="text-xs font-medium text-gray-500 uppercase tracking-wide">Revenue (MTD)</p><p class="mt-1 text-2xl font-bold text-gray-900">$214.8k</p></div>
        <div class="border border-gray-200 rounded-lg p-4"><p class="text-xs font-medium text-gray-500 uppercase tracking-wide">Returns</p><p class="mt-1 text-2xl font-bold text-gray-900">3</p></div>
      </div>
    </div>
    <div role="tabpanel" id="bpanel-orders" aria-labelledby="btab-orders" tabindex="0" class="hidden focus:outline-none">
      <div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="text-left text-xs font-semibold text-gray-500 uppercase tracking-wide border-b border-gray-200"><th class="py-2 pr-4">Order</th><th class="py-2 pr-4">Customer</th><th class="py-2 pr-4">Status</th><th class="py-2 pr-4">Total</th></tr></thead><tbody class="divide-y divide-gray-100"><tr><td class="py-2 pr-4 font-medium text-gray-900">#ORD-1042</td><td class="py-2 pr-4 text-gray-600">Acme Corp</td><td class="py-2 pr-4"><span class="text-xs font-medium text-amber-700 bg-amber-50 border border-amber-200 px-2 py-0.5 rounded">Pending</span></td><td class="py-2 pr-4 text-gray-900">$1,240</td></tr><tr><td class="py-2 pr-4 font-medium text-gray-900">#ORD-1041</td><td class="py-2 pr-4 text-gray-600">Globex</td><td class="py-2 pr-4"><span class="text-xs font-medium text-emerald-700 bg-emerald-50 border border-emerald-200 px-2 py-0.5 rounded">Shipped</span></td><td class="py-2 pr-4 text-gray-900">$860</td></tr></tbody></table></div>
    </div>
    <div role="tabpanel" id="bpanel-inventory" aria-labelledby="btab-inventory" tabindex="0" class="hidden focus:outline-none">
      <div class="grid grid-cols-2 lg:grid-cols-3 gap-4">
        <div class="border border-gray-200 rounded-lg p-4"><div class="flex items-center justify-between"><p class="text-sm font-medium text-gray-900">SKU-001</p><span class="text-xs font-medium text-emerald-700 bg-emerald-50 px-2 py-0.5 rounded">In stock</span></div><p class="mt-1 text-xs text-gray-500">1,240 units</p></div>
        <div class="border border-gray-200 rounded-lg p-4"><div class="flex items-center justify-between"><p class="text-sm font-medium text-gray-900">SKU-014</p><span class="text-xs font-medium text-amber-700 bg-amber-50 px-2 py-0.5 rounded">Low</span></div><p class="mt-1 text-xs text-gray-500">12 units</p></div>
        <div class="border border-gray-200 rounded-lg p-4"><div class="flex items-center justify-between"><p class="text-sm font-medium text-gray-900">SKU-022</p><span class="text-xs font-medium text-rose-700 bg-rose-50 px-2 py-0.5 rounded">Out</span></div><p class="mt-1 text-xs text-gray-500">0 units</p></div>
      </div>
    </div>
    <div role="tabpanel" id="bpanel-reports" aria-labelledby="btab-reports" tabindex="0" class="hidden focus:outline-none">
      <div class="flex items-center justify-between"><p class="text-sm text-gray-600">Generate and export operational reports.</p><button class="text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md px-3 py-1.5">Export CSV</button></div>
    </div>
    <div role="tabpanel" id="bpanel-audit" aria-labelledby="btab-audit" tabindex="0" class="hidden focus:outline-none">
      <ol class="space-y-2 text-sm"><li class="flex gap-3 text-gray-600"><span class="font-mono text-xs text-gray-400">09:42</span> Sarah updated order #ORD-1042</li><li class="flex gap-3 text-gray-600"><span class="font-mono text-xs text-gray-400">09:15</span> System flagged SKU-022 as out of stock</li></ol>
    </div>
  </div>
</div>

<script>
  (function () {
    var list = document.querySelector('[aria-label="Operations"]');
    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-blue-700', s); t.classList.toggle('bg-white', s); t.classList.toggle('border-blue-600', s);
        t.classList.toggle('text-gray-600', !s); t.classList.toggle('bg-gray-50', !s); t.classList.toggle('border-transparent', !s); t.classList.toggle('hover:bg-white', !s); t.classList.toggle('hover:text-gray-900', !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 (e.key === 'Home') idx = 0;
        if (e.key === 'End') idx = tabs.length - 1;
        if (idx !== null) { e.preventDefault(); tabs[idx].focus(); activate(tabs[idx]); }
      });
    });
  })();
</script>
82 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/bordered-tabs

Continue browsing

View all