Tab bar

The primary navigation surface for the mobile app. Fixed to the bottom edge, glass-blurred, iOS safe-area aware. Up to 5 slots — icon above mono label. Active tab teal; everything else muted. It stays out of the way until you need it.

Variants

5-tab layout — groups active

The center slot — "add" — uses an elevated ink circle with a prominent plus. It breaks the flat tab pattern intentionally: adding an expense is the app's core action, always one tap away. The circle lifts 8px above the bar.

The "settle" tab has a coral dot badge — there are outstanding balances to resolve. Badges are always a dot, never a count number.

Sizes

3-tab minimal layout
Slot countUse caseNotes
3 slotsMVP / tight information architectureAlways keep "add" in the center
4 slotsWhen "groups" and "settle" need separationAdd center action moves to a floating button
5 slotsFull navigation with home, groups, add, settle, profileMaximum — never exceed 5

States

StateIcon colorLabel colorNotes
Active--teal--tealIcon shifts 1px upward — subtle lift
Default / inactive--ink-mute--ink-muteVisually recedes
Badged--ink-mute--ink-mute8px coral dot, upper-right of icon area
Disabled40% opacity40% opacityOnly for tabs gated behind onboarding or paywall

On dark surfaces

The glass blur on dark surfaces reads against --dark-canvas. The center "add" button inverts to paper fill in dark mode — ink on dark is too low contrast. Active teal is unchanged — it works on both surfaces.

Anatomy

home
groups
Tab bar (64px, glass-bg)
tab-bar-item (flex:1)
Active — teal icon + label
PartElementNotes
Container.tab-barFixed, bottom 0, 64px height, glass backdrop. Add padding-bottom: env(safe-area-inset-bottom) for iOS home indicator.
Tab item.tab-bar-itemFlex child, equal width (flex: 1). Use <button> for SPA, <a> for multi-page.
Icon wrap.tab-bar-icon-wrapRelative positioned — needed for badge positioning.
Icon.tab-bar-icon24×24, stroked SVG. Color transitions on active/hover.
Label.tab-bar-label10px JetBrains Mono, lowercase. Never title case, never sentence case.
Badge.tab-bar-badge8px coral dot, absolute positioned inside icon-wrap.

Usage

Do Keep labels to one word. Use stroked (not filled) SVG icons at 24px. Mark the current tab with both .active class and aria-current="page". Always include safe-area padding for iPhone.
Don't Don't exceed 5 tabs. Don't use multi-word labels. Don't use filled icons — stroked keeps the bar visually light. Don't hide the tab bar inside sheets or modals.
Do The "add" center action is always an elevated ink circle — this is a fixed pattern, not a design choice per screen. The dot badge is always coral, always a dot, never a number.
Don't Don't animate tab transitions with the bar itself — only the content above it transitions. Don't show a notification count; dots are enough — Settld doesn't badge-shame.

Accessibility

ARIA Wrap the tab bar in <nav aria-label="Main navigation">. The active item gets aria-current="page". Icon-only scenarios (no label) require aria-label on each button.
Keyboard Each tab item is focusable via Tab. Activated by Enter or Space. Focus ring: 2px solid var(--teal) inside the item bounds.
Touch targets Each tab item is at least 44px tall — the 64px bar height ensures this. The center "add" circle (40px) is smaller but surrounded by adequate hit area from the tab cell.

Code

HTML

<nav class="tab-bar" aria-label="Main navigation">
  <button class="tab-bar-item">
    <div class="tab-bar-icon-wrap">
      <div class="tab-bar-icon"><!-- SVG --></div>
    </div>
    <span class="tab-bar-label">home</span>
  </button>

  <!-- Active tab -->
  <button class="tab-bar-item active" aria-current="page">
    <div class="tab-bar-icon-wrap">
      <div class="tab-bar-icon"><!-- SVG --></div>
    </div>
    <span class="tab-bar-label">groups</span>
  </button>

  <!-- Badged tab -->
  <button class="tab-bar-item">
    <div class="tab-bar-icon-wrap">
      <div class="tab-bar-icon"><!-- SVG --></div>
      <div class="tab-bar-badge" aria-label="Has pending settlements"></div>
    </div>
    <span class="tab-bar-label">settle</span>
  </button>
</nav>

Design tokens used

TokenValueRole
--glass-bgrgba(251,248,240,0.72)Tab bar surface
--glass-borderrgba(255,255,255,0.55)Top border
--teal#0E7C66Active icon + label
--ink-mute#8A8276Inactive icon + label
--coral#E76F51Badge dot
--font-monoJetBrains MonoTab labels
--z-nav50Stack order
--d-fast140msColor transitions