App bars

mandatory

Horizontal bar anchored at the top or bottom of an application surface — holds page title, primary navigation actions, and contextual actions. Material parity (`/components/top-app-bar` and `/components/bottom-app-bar`). Covers center/small/medium/large top bar variants and the bottom bar with FAB integration.

Spec — App bars

Facet *isual*of Koder Design. Material parity: https://m3.material.io/components/top-app-bar and https://m3.material.io/components/bottom-app-bar.

2 anchor positions

Position Use Surfaces
*op* Page title + nav + primary actions All surfaces
*ottom* Thumb-reach actions on mobile / tablet portrait Mobile + tablet portrait

Always at most ONE top bar and ONE bottom bar per screen. Do not stack two top bars; nest a secondary toolbar inside content if needed.

R1 — Top bar variants

Variant Height Title When
*enter-aligned* 64 px Centered, single line Mobile, primary screen, simple title
*mall* 64 px Left-aligned, single line Default for most screens
*edium* 112 px Large title below toolbar row, scrolls into row on overflow Hero screen with strong identity
*arge* 152 px Display-style title with breathing room Branded / landing-level screen

Medium and Large COLLAPSE into Small on scroll: title slides up into the toolbar row at scrolly > titleheight. This is the canonical collapse pattern.

Anatomy (small top bar)

┌────────────────────────────────────────────────┐
│  ☰   Page title                  ◷  ⋮  👤      │
└────────────────────────────────────────────────┘
   ↑   ↑                            ↑   ↑   ↑
 nav  title                       action overflow user
  • *eight* 64 px
  • *orizontal padding* 16 px
  • *av icon slot* 24 px icon, left edge, optional
  • *itle* title-large (22/28, weight 500)
  • *ction slots* up to 3 icon buttons + 1 overflow menu
  • *ontainer bg* surface-container (light: tinted; dark: tonal)

R2 — Action slot rules

  • *aximum 3 visible icon actions* rest into overflow ()
  • Order from left to right by frequency / importance
  • Each action is a 24 px icon button with 48 × 48 px hit target
  • Action labels live in tooltip (long-press on mobile, hover on desktop)
  • Disable actions don't collapse — show at 38% opacity

R3 — Title behavior

Mode Behavior
*tatic* Title is text only
*ith subtitle* Title + 14 px subtitle below (small bar height 72 px)
*ith breadcrumb* Stack: breadcrumb above small title; OR replace title with full breadcrumb path
*ditable* Tap title opens inline rename input (rare; for renameable doc/board screens)

Never wrap title to a 2nd line in small/center. Truncate with ellipsis or use Medium/Large variant.

R4 — Scroll behavior

Variant On scroll-down On scroll-up
*mall / Center* Surface tint deepens (elevation overlay) when content is below Tint clears at top
*edium / Large* Title row collapses; toolbar stays Title row expands back when at top
*inned* Always visible (default)
*iftonscroll* Hidden on scrolldown past threshold; revealed on scrollup Reappears on scrollup
*lways-show* Never hides

Pick ONE scroll behavior per screen; don't mix.

R5 — Bottom app bar (mobile primary)

Anatomy:

┌────────────────────────────────────────────────┐
│  ⌂   ⌥   ⌽                                  ⊕  │
└────────────────────────────────────────────────┘
   ↑   ↑   ↑                                  ↑
   actions (left-aligned)                    FAB (right)
  • *eight* 80 px (includes 24 px FAB cradle space)
  • *ction slots* up to 4 icon buttons, left-aligned
  • *AB cradle* right side, FAB sits on bar (notched on Material 2,

    flat on Material 3)

  • Container bg: surface-container
  • Elevation: 2 dp (sits above scrolling content)

Use bottom bar ONLY on mobile + tablet portrait. On larger surfaces, move actions to top bar or side rail.

R6 — Bottom bar + FAB

FAB position Use
*ight* Default; thumb-reach for primary action
*enter* Single dominant action; bar holds 2 actions max each side
*o FAB* Bottom bar with up to 4 actions, no embedded FAB

FAB anchored to bottom bar cradle stays visible when bar scrolls.

R7 — Surface adaptation

App bars MUST adapt per app-layout/window-size-classes.kmd:

Class Top bar Bottom bar
Compact (< 600 dp) Small + Center-aligned Allowed
Medium (600-839 dp) Small (medium for hero) Allowed (tablet portrait)
Expanded (840-1199 dp) Small / Medium Forbidden (use side rail)
Large (≥ 1200 dp) Small / Medium Forbidden (use drawer)

R8 — States

State Visual
*est* Default colors
*crolled content underneath* Surface tint deepens (Material 3 elevation overlay), 3 dp tonal lift
*overed (icon button)* State layer 8% on icon hit area
*ressed* State layer 12%
*ocused* 2 px focus ring around icon button
*isabled (action)* 38% opacity

R9 — Accessibility

  • Top bar: role="banner" on container
  • Title: heading level matches page hierarchy (h1 on landing page)
  • Nav icon: aria-label="Open navigation" or specific verb
  • Actions: each icon has aria-label; overflow has aria-label="More actions"
  • Bottom bar: role="navigation" if actions navigate; else no role
  • Keyboard order: nav → title (focusable if editable) → actions → overflow → FAB
  • Skiptocontent link before app bar for screen readers

R10 — Per-preset variation

Preset Top bar Bottom bar
material3 Tonal surface, no border Notch flat, 24 dp corner
material2 Flat color, 4 dp shadow FAB notch on bar
ios_cupertino Translucent blur, 1 px hairline border Tab bar pattern (not bottom app bar — re-map to nav bar)
gnome Headerbar style, integrated with window controls Not used (desktop)
windows_11 Mica backdrop, integrated title bar Not used (desktop)
brutalist Solid color, no elevation, thick 4 px bottom border Sharp corners, no FAB cradle
terminal_classic Single text line ═ Page Title ═ Bottom row [F1] [F2] [F3] style

R11 — Forbidden patterns

  • ❌ Two top bars stacked on one screen
  • ❌ Bottom bar on Expanded/Large window-size class
  • ❌ More than 3 icon actions visible in top bar (use overflow)
  • ❌ More than 4 actions in bottom bar
  • ❌ Title that wraps to 2 lines in Small / Center variant
  • ❌ Bottom bar without safearea inset on iOS / Android gesturenav
  • ❌ Hiding action labels entirely (always provide tooltip + aria-label)
  • ❌ Animating the title across the entire bar width on collapse (jarring)
  • app-layout/safe-area.kmd — bottom bar must respect gesture-nav inset
  • app-layout/window-size-classes.kmd — adaptive per breakpoint
  • themes/elevation.kmd — scroll-state tonal overlay
  • themes/color-roles.kmdsurface-container token
  • interaction/states.kmd — icon button states
  • foundations/elements.kmd — Container family (bar) + Control family (actions)
  • components/navigation.kmd — sibling for primary navigation containers

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/app-bars.kmd