Component
Animated Tabs
Tabs with a smoothly animating sliding underline indicator that glides between active tabs. Great for project management workspaces with board, timeline, calendar, and files views.
- Component
- Tailwind
- HTML
- MIT
What it does
Capabilities
- Sliding underline
- Smooth transition
- Resize-aware
- Kanban/timeline/calendar panels
- Arrow-key navigation
Preview
Live component
9:41 100%
devsnips.site/library/tailwind/components/tabs/animated-tabs/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Tabs/animated-tabs Tailwind/Components/Tabs/animated-tabs <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> # Animated Tabs
Tabs with animated active indicator.
## Usage
```bash
npx devsnips add Tailwind/Components/Tabs/animated-tabs
```
Copy from `code.html`. Prefer tablist/tab/tabpanel roles when implementing interactivity.
## File Structure
`code.html` · `preview.html` · `metadata.json` · `README.md` 92 lines UTF-8 · LF · Spaces: 2
DevSnips AI ready Claude · Cursor · Windsurf
Agent skill & Model Context Protocol
Pass this component straight into your AI workflow. DevSnips exposes each resource as a structured, addressable registry entry, so your agent installs the real files instead of approximating them.
devsnips://components/tabs/animated-tabs I want to use this DevSnips resource in production: Page: https://devsnips.site/library/tailwind/components/tabs/animated-tabs/ Install: npx devsnips add Tailwind/Components/Tabs/animated-tabs This is the Animated Tabs — Tabs with a smoothly animating sliding underline indicator that glides between active tabs. Great for project management workspaces with board, timeline, calendar, and files views. Use this DevSnips resource as the starting point for my project. Adapt it to my project's stack and conventions, fix any issues, and make it production-ready while preserving its intended design and behavior.
Paste into ChatGPT, Claude or your agent — it already carries the page URL and the exact install path.
Resource URI
devsnips://components/tabs/animated-tabs