Component
Segmented Tabs
iOS-style segmented control with a sliding indicator that animates between segments. Used for switching time ranges and compact view modes.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.dev/library/tailwind/components/tabs/segmented-tabs/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Tabs/segmented-tabs Tailwind/Components/Tabs/segmented-tabs <div class="w-full max-w-md">
<div role="tablist" aria-label="View mode" class="relative inline-flex items-center gap-1 p-1 bg-gray-100 rounded-xl">
<span class="seg-indicator absolute top-1 bottom-1 left-1 w-[calc(33.333%-0.25rem)] bg-white rounded-lg shadow-sm transition-transform duration-300 ease-out" aria-hidden="true"></span>
<button role="tab" id="gtab-day" aria-selected="true" aria-controls="gpanel-day" tabindex="0"
class="relative z-10 flex-1 px-4 py-1.5 text-sm font-medium text-gray-900 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded-lg">
Day
</button>
<button role="tab" id="gtab-week" aria-selected="false" aria-controls="gpanel-week" tabindex="-1"
class="relative z-10 flex-1 px-4 py-1.5 text-sm font-medium text-gray-500 hover:text-gray-800 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded-lg">
Week
</button>
<button role="tab" id="gtab-month" aria-selected="false" aria-controls="gpanel-month" tabindex="-1"
class="relative z-10 flex-1 px-4 py-1.5 text-sm font-medium text-gray-500 hover:text-gray-800 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded-lg">
Month
</button>
</div>
<div class="mt-5">
<div role="tabpanel" id="gpanel-day" aria-labelledby="gtab-day" tabindex="0" class="rounded-xl border border-gray-200 p-4 focus:outline-none">
<p class="text-xs font-medium text-gray-500">Today, Aug 4</p>
<p class="mt-1 text-lg font-semibold text-gray-900">2h 14m focused</p>
<div class="mt-3 flex h-2 rounded-full overflow-hidden bg-gray-100">
<div class="bg-blue-500" style="width:42%"></div><div class="bg-blue-300" style="width:28%"></div><div class="bg-gray-300" style="width:30%"></div>
</div>
</div>
<div role="tabpanel" id="gpanel-week" aria-labelledby="gtab-week" tabindex="0" class="hidden rounded-xl border border-gray-200 p-4 focus:outline-none">
<p class="text-xs font-medium text-gray-500">This week</p>
<p class="mt-1 text-lg font-semibold text-gray-900">14h 02m focused</p>
<div class="mt-3 flex items-end gap-1.5 h-16">
<div class="flex-1 bg-blue-500 rounded-t" style="height:60%"></div><div class="flex-1 bg-blue-500 rounded-t" style="height:80%"></div><div class="flex-1 bg-blue-500 rounded-t" style="height:45%"></div><div class="flex-1 bg-blue-500 rounded-t" style="height:70%"></div><div class="flex-1 bg-blue-500 rounded-t" style="height:90%"></div><div class="flex-1 bg-blue-400 rounded-t" style="height:55%"></div><div class="flex-1 bg-blue-400 rounded-t" style="height:40%"></div>
</div>
</div>
<div role="tabpanel" id="gpanel-month" aria-labelledby="gtab-month" tabindex="0" class="hidden rounded-xl border border-gray-200 p-4 focus:outline-none">
<p class="text-xs font-medium text-gray-500">August</p>
<p class="mt-1 text-lg font-semibold text-gray-900">62h 30m focused</p>
<p class="mt-2 text-xs text-emerald-600 font-medium">▲ 18% vs last month</p>
</div>
</div>
</div>
<script>
(function () {
var list = document.querySelector('[aria-label="View mode"]');
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('.seg-indicator');
function moveIndicator(tab) {
if (!indicator) return;
var pad = 4;
indicator.style.left = (tab.offsetLeft + pad) + 'px';
indicator.style.width = (tab.offsetWidth - pad * 2) + 'px';
indicator.style.top = pad + 'px';
indicator.style.height = (list.offsetHeight - pad * 2) + '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 (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> # Segmented Tabs
Segmented control style tabs.
## Usage
```bash
npx devsnips add Tailwind/Components/Tabs/segmented-tabs
```
Copy from `code.html`.
## File Structure
`code.html` · `preview.html` · `metadata.json` · `README.md` 82 lines UTF-8 · LF · Spaces: 2
Continue browsing