Nav bar

● Stable · v0.1

A floating bottom navigation bar — a rounded, translucent, shadowed pill that hovers above the screen. Two to five destinations, each an icon over a label, with the active one lifted onto a neutral pill and its icon filled.

In context

The bar floats above the content; on the web it frosts what's behind it.

Try it

States & variants

Purpose

The nav bar is the app's top-level switch between destinations — Home, Record, Insights, Profile. Floating it (rather than pinning a full-width bar to the very bottom) keeps it reachable with a thumb, frames the content, and feels modern without shouting.

The floating look

  • A rounded pill centred above the bottom edge, inset from the sides.
  • A translucent surface (surface.glass) over a backdrop blur on web; on native it falls back to the same translucent surface plus a soft shadow (no blur dependency).
  • A shadow (elevation.lg) so it reads as hovering above the page, not stuck to it.
  • The active destination sits on a quiet neutral pill (no brand colour), its icon filled and its label in the strongest text colour; the rest stay outlined and secondary.

Anatomy

  • Bar — the floating container. Positions itself absolutely at the bottom of its parent (which must be flex:1 / relative); set floating={false} to dock it inline.
  • Item — an equal-width slot (icon over a short label, ≥48dp) that fills with a neutral pill (background.tertiary) when active.
  • Icon — passed per item as a render function that receives active, so you show a filled glyph when active and an outline when not (and the colour follows the state). The package stays icon-free.
  • Badge — an optional dot (badge: true) or count (badge: 5) on an item for unseen activity.

Code

import { NavBar } from '@daytwo/components'
// Use an icon set with filled + outline pairs (e.g. Ionicons):
import { IoHome, IoHomeOutline, IoPieChart, IoPieChartOutline } from 'react-icons/io5'
const [tab, setTab] = useState('home')
// Each item shows the FILLED glyph when active, the OUTLINE when not.
<View style={{ flex: 1 }}>
<YourScreen />
<NavBar
value={tab}
onChange={setTab}
items={[
{ value: 'home', label: 'Home',
icon: ({ color, size, active }) =>
active ? <IoHome color={color} size={size} /> : <IoHomeOutline color={color} size={size} /> },
{ value: 'insights', label: 'Insights', badge: 3,
icon: ({ color, size, active }) =>
active ? <IoPieChart color={color} size={size} /> : <IoPieChartOutline color={color} size={size} /> },
]}
/>
</View>

The component passes active to each item's icon, so you swap between the filled and outline glyph. Add bottom padding to the scrolling content so the last items clear the floating bar, and raise bottomInset to sit above a device's home indicator.

When to use

  • For the app's 2–5 top-level destinations, reachable from anywhere.
  • When a thumb-friendly, modern bottom bar fits the product.

When NOT to use

  • To section one screen's content (Sales / Customers) — that's Tabs.
  • To toggle one value (Today / This week) — that's a segmented control.
  • For more than five destinations — they get cramped; group some under a "More" or rethink the IA.

Anti-patterns

Do
Four clear destinations, each an icon and a short label, the active one obvious. Comfortable thumb targets with room to breathe.
Don't
Six tiny items crammed into the pill — labels collide, targets shrink below 48dp, and nothing is the clear next thing.
Destinations, not actions

A nav bar switches where you are; it never performs an action. "Record a sale" belongs on the screen as a button (or as a destination that opens the record flow) — not mixed in as a fifth tab that behaves differently from the rest.

Edge cases

Active destination
Neutral pill, filled icon, strongest label
WhyThe current place is unmistakable without leaning on brand colour
Unseen activity
A dot (badge: true) or count on the item
WhyDraws the eye without a number when one isn't needed
Icons only
showLabels={false} for a compact bar
WhySome products don't need labels once learned
Long labels
Labels truncate to one line
WhyThe pill keeps its shape on small screens
Home indicator
Raise bottomInset so the bar clears it
WhyThe bar shouldn't fight the system gesture area
Content behind
Pad the scroll content's bottom
WhyThe last row isn't hidden under the floating bar
Dark mode
Glass, border, and shadow follow the theme
WhyThe float reads in both schemes

Tokens used

color.surface.glasscolor.background.tertiarycolor.text.primarycolor.text.secondarycolor.border.subtlecolor.feedback.errorSolidradius.pillelevation.lgtouchTargets.minmotion.duration.fasttypography.caption2