Bottom Nav
The mobile tab bar — three to five destinations, pinned to the bottom where thumbs are, with the home-indicator safe area accounted for.
src/components/ui/bottom-nav.tsxAbout
From the component's own source, where it was written.
The mobile tab bar: three to five destinations, pinned to the bottom.
**Bottom, because that is where thumbs are.** On a phone held one-handed the top of the screen is the hardest region to reach and the bottom third is the easiest — which is why every mobile OS puts primary navigation there and why a top nav bar on mobile costs a reach or a second hand.
**It respects the home indicator.** env(safe-area-inset-bottom) is added to the padding, so on a notched phone the bar sits above the gesture area instead of underneath it, where the last few pixels of every tap get eaten by the system. This is the single most common defect in hand-rolled tab bars.
**Destinations, not actions.** These switch *where you are*; a tab bar with "Share" in it is a toolbar wearing the wrong clothes. Keep it to five — past that the targets fall below the ~44px comfortable minimum and labels truncate to nonsense.
It renders <nav> + a list of links, with aria-current="page" on the active one — the same markup as any other navigation, so it is announced as navigation and works with the browser's own history.
Install
npx astralyx-ui add bottom-nav
Usage
import { BottomNav } from '@/components/ui/bottom-nav'
<BottomNav items={items} value={tab} onChange={setTab} />Composer
Change the props and the source below follows.
<BottomNav
items={items}
value={tab}
onChange={setTab}
showLabels={true}
/>Examples
Five destinations, with badges
<BottomNav items={items} value={tab} onChange={setTab} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
Types
Behaviour
| Topic | Detail | Description |
|---|---|---|
| bottom | where thumbs are | Held one-handed, the top of a phone is the hardest region to reach. A top nav bar on mobile costs a reach or a second hand. |
| safe area | env(safe-area-inset-bottom) | Added to the padding, so the bar clears the home indicator. Without it the last row of pixels is not tappable — the most common defect in hand-rolled tab bars. |
| destinations, not actions | keep it to five | A tab bar with "Share" in it is a toolbar wearing the wrong clothes. Past five, targets fall below ~44px and labels truncate to nonsense. |
| aria-current | page | The navigation equivalent of aria-selected. Signalling the current page with colour alone says nothing to a screen reader. |