Component
TabBar
TabBar provides touch-sized app navigation for three to five destinations without coupling the component to a specific router. Compose each item with your router's link component to preserve client-side navigation.
Preview
Installation
pnpm dlx shadcn@latest add https://pwaui.com/r/tab-bar.jsonUsage
import Link from "next/link"import { Home, Search, User } from "lucide-react"import { TabBar } from "@/components/ui/tab-bar"
export function Navigation() { return ( <TabBar> <TabBar.Item render={<Link href="/" />} icon={<Home />} label="Home" active /> <TabBar.Item render={<Link href="/search" />} icon={<Search />} label="Search" badge={3} badgeLabel="3 new results" /> <TabBar.Item render={<Link href="/profile" />} icon={<User />} label="Profile" /> </TabBar> )}Anatomy
TabBarTabBar.ItemComposition
See how PWAProvider, AppShell, SafeArea, NavigationBar, and TabBar divide viewport, scrolling, safe-area, and navigation responsibilities.
Behavior notes
- Inside AppShell, place TabBar within AppShell.Footer.
- Use render={<Link href="/search" />} with Next.js, or render={<NavLink to="/search" />} with React Router. TanStack Router follows the same render pattern.
- Items render buttons by default. href remains available for external links and no-router apps, but performs a document navigation.
- Active items expose aria-current=page. Use three to five stable application destinations.
Platform limitations
- This is web navigation chrome, not native tabs. It does not integrate with OS gesture navigation, and in an installed iOS PWA the home-indicator area must be handled with the footer safe-area inset.
Accessibility
Every item requires a visible label. Supply badgeLabel whenever badge conveys information so assistive technology hears what the value means.