Banners

mandatory

Persistent informational bar at the top of a content region — carries a message and 1-2 actions. Material parity (`/components/banners`). Distinguished from snackbars (transient) and dialogs (modal); banners stay until dismissed and never block interaction.

Facet Visual of Koder Design. Material parity: https://m3.material.io/components/banners.

Where they fit

Component Modality Persistence
Banner Non-modal Persistent until user dismisses / acts
Snackbar Non-modal Transient (4-10 s)
Dialog Modal Persistent until user dismisses

Pick banner when: information requires action OR awareness over multiple page interactions, but does NOT need to block the user.

Anatomy

┌────────────────────────────────────────────────────────┐
│  ⓘ  Your subscription expires in 3 days.               │
│      Renew now to keep access.                         │
│                                  [Renew]   [Dismiss]   │
└────────────────────────────────────────────────────────┘
   ↑   ↑                              ↑         ↑
 icon  message                      action1   action2
  • Height: 54 px (single line) / 90 px (two lines) / auto
  • Padding: 16 px vertical, 24 px horizontal
  • Icon: 24 px, optional, leading
  • Message: body-medium (14/20, weight 400)
  • Actions: text buttons, trailing
  • Border: 1 px bottom outline-variant
  • Background: surface-container-low

R1 — Variants by tone

Tone Use Icon Background
Info General announcement info (ⓘ) surface-container-low
Warning Action needed soon warning (⚠) warning-container
Error Action needed now / degraded service error (✕) error-container
Success / promo Positive announcement check (✓) success-container (extended)

Color alone never carries meaning — always pair tone with icon + text.

R2 — Action rules

  • 0 actions: dismiss-only banner; tap × at end OR auto-show

    dismiss after read

  • 1 action: action + dismiss button (× icon at end)
  • 2 actions: primary + secondary text buttons; no separate ×

    (secondary serves as dismiss when labeled "Dismiss")

Maximum 2 visible actions. Don't put overflow menu in a banner.

R3 — Placement

Placement When
Top of page content (default) One banner per page
Top of section One banner scoped to a section
Inside list / form Inline banner about a specific item

Never stack multiple banners. If multiple announcements pending, show the highest-priority one first; queue the rest after dismissal.

App bar sits ABOVE banner — banner anchors below the top app bar.

R4 — Persistence and state

  • Banner stays visible across scroll (does not stick to viewport;

    scrolls with content)

  • Dismissal is REMEMBERED per user + per banner ID — don't re-show

    the same dismissed banner unless conditions change

  • For "cookie consent" or "system upgrade" type banners, document

    re-show conditions explicitly

R5 — Animation

  • Appear: slide-down from top edge (motion-medium, ~250 ms)
  • Dismiss: fade-out + slide-up (motion-fast, ~150 ms)
  • Content below shifts smoothly when banner appears / disappears

    (no abrupt layout jump)

  • Reduced motion: instant show / hide

R6 — Accessibility

  • role="status" (info) or role="alert" (warning/error)
  • aria-live="polite" (status) / assertive (alert)
  • Action buttons have full labels (not "Click here")
  • Dismiss × button: aria-label="Dismiss banner"
  • Keyboard: Tab into action buttons → dismiss button; Esc dismisses

    (when allowed by banner type)

  • Icon is decorative if message conveys tone in words — aria-hidden

R7 — Mobile responsiveness

Width Behavior
≥ 600 dp Single row, actions trailing
< 600 dp Two rows: message on top, actions on second row (left-aligned)

Truncate to 2 lines max on Compact width; expand to fit when actions move to a separate row.

R8 — Density

Density Padding Height (single line)
Compact 12 px / 20 px 48 px
Default 16 px / 24 px 54 px
Comfortable 20 px / 28 px 64 px

R9 — Per-preset variation

Preset Visual
material3 Tonal background by tone, no border, 24 px radius corners on rounded variant
material2 Sharp corners, 1 px hairline border
ios_cupertino Top-anchored, slight translucency, dismiss as swipe-up gesture
gnome InfoBar style — flat tonal, 6 px border-radius
windows_11 Mica backdrop tint, accent color border-left
brutalist Solid color block, 4 px thick border, no rounded corners
terminal_classic Border-style box ┌── INFO ───┐ ... └──[OK]─┘

R10 — Forbidden patterns

  • ❌ Stacking multiple banners on one page
  • ❌ Banner over modal (banner is non-modal; modal already blocks)
  • ❌ Auto-dismissing banner with a timer (use snackbar instead)
  • ❌ More than 2 actions
  • ❌ Putting form inputs / interactive controls inside banner body
  • ❌ Showing the same dismissed banner without user-visible state change
  • ❌ Color-only tone signal (always pair with icon + words)
  • ❌ Sticking banner to viewport on scroll (annoying; use snackbar

    if must stay visible)

  • themes/color-roles.kmd — tonal container tokens
  • themes/elevation.kmd — banner sits at 0 dp (within surface)
  • components/snackbars.kmd — transient sibling
  • components/dialogs.kmd — modal sibling
  • foundations/elements.kmd — Container + Marker families