Component
Mobile Tabs
Bottom mobile tab navigation bar with icons, labels, and a notification badge. Switches app screens within a phone-style frame. Built for native-feeling mobile web apps.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.dev/library/tailwind/components/tabs/mobile-tabs/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Tabs/mobile-tabs Tailwind/Components/Tabs/mobile-tabs <div class="w-full max-w-sm mx-auto">
<!-- App screen -->
<div class="relative bg-gray-50 border border-gray-200 rounded-3xl overflow-hidden shadow-sm" style="min-height:520px">
<!-- Top bar -->
<div class="bg-white px-5 py-4 border-b border-gray-100 flex items-center justify-between">
<h2 class="text-base font-semibold text-gray-900">Home</h2>
<div class="w-9 h-9 rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 flex items-center justify-center text-white text-sm font-semibold">S</div>
</div>
<!-- Panels -->
<div class="p-5 pb-28">
<div role="tabpanel" id="mob-panel-home" aria-labelledby="mob-tab-home" tabindex="0" class="focus:outline-none">
<p class="text-xs font-medium text-indigo-600">Good morning, Sarah</p>
<h3 class="mt-1 text-lg font-bold text-gray-900">Pick up where you left off</h3>
<div class="mt-4 rounded-2xl bg-gradient-to-br from-indigo-500 to-purple-600 p-4 text-white">
<p class="text-sm font-medium">Continue: Onboarding flow</p>
<p class="mt-1 text-xs text-indigo-100">3 of 5 steps complete</p>
<div class="mt-3 h-1.5 bg-white/30 rounded-full overflow-hidden"><div class="h-full bg-white rounded-full" style="width:60%"></div></div>
</div>
<div class="mt-4 grid grid-cols-2 gap-3">
<div class="rounded-xl bg-white border border-gray-200 p-3"><p class="text-sm font-medium text-gray-900">Tasks</p><p class="text-xs text-gray-500">4 due today</p></div>
<div class="rounded-xl bg-white border border-gray-200 p-3"><p class="text-sm font-medium text-gray-900">Messages</p><p class="text-xs text-gray-500">2 unread</p></div>
</div>
</div>
<div role="tabpanel" id="mob-panel-search" aria-labelledby="mob-tab-search" tabindex="0" class="hidden focus:outline-none">
<div class="flex items-center gap-2 bg-white border border-gray-200 rounded-xl px-3 py-2.5">
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>
<input type="text" placeholder="Search people, files…" class="flex-1 bg-transparent text-sm outline-none">
</div>
<p class="mt-4 text-xs font-semibold text-gray-500 uppercase tracking-wide">Recent</p>
<ul class="mt-2 space-y-1 text-sm text-gray-700"><li class="py-2 border-b border-gray-100">Design system tokens</li><li class="py-2 border-b border-gray-100">Q3 roadmap</li><li class="py-2">Sarah Mitchell</li></ul>
</div>
<div role="tabpanel" id="mob-panel-notifications" aria-labelledby="mob-tab-notifications" tabindex="0" class="hidden focus:outline-none">
<h3 class="text-lg font-bold text-gray-900">Notifications</h3>
<ul class="mt-3 space-y-2">
<li class="flex gap-3 rounded-xl bg-white border border-gray-200 p-3"><span class="w-2 h-2 mt-1.5 rounded-full bg-indigo-500"></span><div><p class="text-sm font-medium text-gray-900">New comment on your task</p><p class="text-xs text-gray-500">2 min ago</p></div></li>
<li class="flex gap-3 rounded-xl bg-white border border-gray-200 p-3"><span class="w-2 h-2 mt-1.5 rounded-full bg-gray-300"></span><div><p class="text-sm font-medium text-gray-900">Weekly digest ready</p><p class="text-xs text-gray-500">1h ago</p></div></li>
</ul>
</div>
<div role="tabpanel" id="mob-panel-profile" aria-labelledby="mob-tab-profile" tabindex="0" class="hidden focus:outline-none">
<div class="flex items-center gap-3">
<div class="w-14 h-14 rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 flex items-center justify-center text-white text-lg font-semibold">S</div>
<div><p class="text-base font-semibold text-gray-900">Sarah Mitchell</p><p class="text-xs text-gray-500">sarah@acme.io</p></div>
</div>
<ul class="mt-5 divide-y divide-gray-100 text-sm">
<li class="py-3 flex items-center justify-between"><span class="text-gray-700">Account settings</span><span class="text-gray-400">›</span></li>
<li class="py-3 flex items-center justify-between"><span class="text-gray-700">Help & support</span><span class="text-gray-400">›</span></li>
<li class="py-3 flex items-center justify-between"><span class="text-rose-600">Sign out</span><span class="text-gray-400">›</span></li>
</ul>
</div>
</div>
<!-- Bottom tab bar -->
<nav class="absolute bottom-0 inset-x-0 bg-white/95 backdrop-blur border-t border-gray-200" aria-label="Primary">
<div role="tablist" class="grid grid-cols-4">
<button role="tab" id="mob-tab-home" aria-selected="true" aria-controls="mob-panel-home" tabindex="0"
class="flex flex-col items-center gap-0.5 py-2.5 text-indigo-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/></svg>
<span class="text-[10px] font-medium">Home</span>
</button>
<button role="tab" id="mob-tab-search" aria-selected="false" aria-controls="mob-panel-search" tabindex="-1"
class="flex flex-col items-center gap-0.5 py-2.5 text-gray-400 hover:text-gray-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>
<span class="text-[10px] font-medium">Search</span>
</button>
<button role="tab" id="mob-tab-notifications" aria-selected="false" aria-controls="mob-panel-notifications" tabindex="-1"
class="relative flex flex-col items-center gap-0.5 py-2.5 text-gray-400 hover:text-gray-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500">
<span class="relative">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/></svg>
<span class="absolute -top-0.5 -right-0.5 w-2 h-2 bg-rose-500 rounded-full ring-2 ring-white"></span>
</span>
<span class="text-[10px] font-medium">Alerts</span>
</button>
<button role="tab" id="mob-tab-profile" aria-selected="false" aria-controls="mob-panel-profile" tabindex="-1"
class="flex flex-col items-center gap-0.5 py-2.5 text-gray-400 hover:text-gray-600 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-indigo-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>
<span class="text-[10px] font-medium">Profile</span>
</button>
</div>
</nav>
</div>
</div>
<script>
(function () {
var list = document.querySelector('[aria-label="Primary"]');
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-indigo-600', s);
t.classList.toggle('text-gray-400', !s);
t.classList.toggle('hover:text-gray-600', !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> # Mobile Tabs
Mobile-friendly tab bar.
## Usage
```bash
npx devsnips add Tailwind/Components/Tabs/mobile-tabs
```
Copy from `code.html`.
## File Structure
`code.html` · `preview.html` · `metadata.json` · `README.md` 112 lines UTF-8 · LF · Spaces: 2
Continue browsing