Zetta v1.6

Components · Data display & feedback

Banner

A full-width strip pinned above the content for system-level messages — maintenance, an outage, or an announcement. It carries an icon, a centred message, an optional inline action, and a dismiss control. Use it sparingly; one at a time.

Preview

Zetta v1.2 is here — the palette just got an upgrade.
Scheduled maintenance tonight at 02:00 UTC.

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Banner" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `banner` spec (variants: warning, danger, announcement) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `banner` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

╔══════════════════════════════════════════════╗
║  ⚠  Scheduled maintenance on Jan 15 at 2am  [Learn more]  ✕  ║
╚══════════════════════════════════════════════╝
State Visual
Default Semantic fill, icon, title, body, optional action
Dismissed Not rendered (removed from DOM, or display: none)
With action — button hover Action button applies its own hover state
With dismiss — button hover Dismiss icon button applies button-icon-hover

When to use

  • System-wide outage or degraded service notifications.
  • Scheduled maintenance windows that affect all users.
  • Time-sensitive product announcements.

When not to use

  • Page-specific messages — use Section Message or Toast.
  • Validation errors — use inline field errors.
  • More than one message simultaneously — queue or consolidate.

Do

  • Keep message text under 100 characters.
  • Provide a dismissal mechanism for non-blocking messages.
  • Use danger sparingly — overuse desensitizes users.

Don't

  • Don't use banners for success states — use Toast.
  • Don't stack multiple banners — show only the highest-priority one.
  • Lead with the impact, not the cause: "Uploads are unavailable", not "S3 connection timeout error".
  • Use "we" not "you" in error messages: "We're experiencing issues", not "You cannot upload".
  • Keep action link label to 2–3 words: "Learn more", "View status".

Keyboard

Key Behavior
Tab Move focus to action button or dismiss button
Enter / Space Activate focused button
Escape Dismiss the banner (if dismissible)

Accessibility

  • ARIA role: role="alert" for warning/danger; role="status" for announcement — both are live regions.
  • Dismiss button: aria-label="Dismiss banner".
  • role="alert" is aggressive — screen readers interrupt the current reading to announce it. Use only for warning/danger, never for announcements.

Spec

Values and token references resolved straight from the Zetta spec.

banner
width
100%
display
flex
alignItems
center
justifyContent
center
gap
{spacing.sm}
paddingX
{spacing.xl}
paddingY
{spacing.sm}
fontFamily
Geist
fontSize
14px
fontWeight
400
lineHeight
1.40
minHeight
40px
position
relative
banner-warning
backgroundColor
{colors.warning-bg}
textColor
{colors.warning-text}
iconColor
{colors.warning}
banner-danger
backgroundColor
{colors.danger-bg}
textColor
{colors.danger-text}
iconColor
{colors.danger}
banner-announcement
backgroundColor
{colors.brand-bg}
textColor
{colors.body}
iconColor
{colors.brand}
banner-icon
size
{icons.sizeMap.md}
flexShrink
0
banner-action
marginLeft
{spacing.sm}
fontWeight
500
textDecoration
underline
cursor
pointer
banner-dismiss
position
absolute
right
{spacing.md}
top
50%
transform
translateY(-50%)
iconSize
{icons.sizeMap.md}
iconColor
{colors.muted}
cursor
pointer
borderRadius
{rounded.base}
padding
{spacing.xs}
banner-dismiss-hover
backgroundColor
{colors.surface-muted}
textColor
{colors.ink}

Known gaps

  • Banner queue — when multiple system events fire simultaneously, no queuing or priority order is defined.
  • Banner persist-across-routes behavior — whether the banner survives navigation is product responsibility; no token or prop governs it.