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
Build with the skill
No package to install — hand this to your AI to generate or migrate the component in your stack.
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
dangersparingly — 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.