<!-- Protocore Design System — Banner -->
# Banner

- **Category:** Feedback (`feedback`)
- **Slug:** `feedback/banner`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Banner } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/feedback/banner

> A full-width tinted notice band for page- or section-level status, with optional action and dismiss.

## When to use it

Use a **Banner** for a persistent, surface-wide condition the user should notice but that doesn't block them: scheduled maintenance, a degraded region, unclaimed rewards, a trial about to expire.

- Loading the surface *failed* and there's nothing to show? That's an [ErrorState](/feedback/error-state), which replaces the content rather than sitting above it.
- Tied to a single field or row? Use an [InlineMessage](/feedback/inline-message).
- A note in the reading flow? Use a [Callout](/feedback/callout).
- A fleeting confirmation of an action? Use a [Toast](/feedback/toast).

Keep banners rare — a page stacked with them trains users to ignore all of them.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `action` | `ReactNode` | no | — | Trailing action slot (e.g. a Button). |
| `children` | `ReactNode` | no | — | Body copy (also accepted via `children`). |
| `className` | `string` | no | — | — |
| `dismissible` | `boolean` | no | `false` | Show a dismiss (×) button. |
| `dismissLabel` | `string` | no | `Dismiss` | Accessible label for the dismiss button. |
| `icon` | `ReactNode` | no | — | Optional leading icon. |
| `onDismiss` | `(() => void)` | no | — | Called when the banner is dismissed; its presence also shows the × button. |
| `style` | `CSSProperties` | no | — | — |
| `title` | `ReactNode` | no | — | Bold headline line. |
| `tone` | `enum` | no | `info` | Status tone; drives the tint background and left rule. |

## Examples

### Basics

A `tone`, a `title`, and body copy as children. It spans the full width of its container — mount it at the top of a page or section.

```tsx
import { Banner } from "@protocore/pds";

export default function Basics() {
  return (
    <Banner tone="info" title="Scheduled maintenance">
      The indexer will be read-only on Sunday 04:00–05:00 UTC.
    </Banner>
  );
}
```

### Tones

Each status tone sets the tint and left rule. Add a leading `icon` to reinforce urgent tones like `danger`.

```tsx
import { Banner, VStack } from "@protocore/pds";
import { AlertTriangle } from "lucide-react";

export default function Tones() {
  return (
    <VStack gap={3}>
      <Banner tone="success" title="Upgrade complete">
        All validators are running protocol v2.4.
      </Banner>
      <Banner tone="danger" icon={<AlertTriangle size={18} />} title="Consensus stalled">
        The network has not finalised a block in 3 epochs.
      </Banner>
    </VStack>
  );
}
```

## Do & don't

**Do**

- Use it for persistent, page- or section-level conditions.
- Give it a single, clear `action` when there's something to do.
- Make it `dismissible` when the notice is non-critical.
- Add a leading icon to reinforce urgent tones.

**Don't**

- Stack several banners — collapse them or prioritize one.
- Use a Banner for transient action feedback — that's a Toast.
- Make a blocking error dismissible, hiding the problem.
- Bury a critical, non-dismissible condition below the fold.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Reaches the action control, then the dismiss (×) button, when present. |
| `Enter / Space` | Activates the focused action or dismiss button. |

**Notes**

- The root is `role="status"` (polite live region) — appropriate for informational notices; it isn't announced assertively.
- For a blocking, must-read error, prefer an ErrorState (`role="alert"`) over a Banner.
- The dismiss button has an accessible label (`dismissLabel`, default "Dismiss") since its glyph is a bare ×.
- The leading `icon` is decorative and `aria-hidden`; the title and body carry the message.

## Related

`callout`, `inline-message`, `toast`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
