# Status Banner

> Information, success, warning, and error states with optional actions and dismissal.

- Category: Feedback
- Kind: component
- Page: https://uaiblocks.dev/components/status-banner
- Registry item: https://uaiblocks.dev/r/status-banner.json
- Source: https://github.com/victor-teles/uai/blob/main/src/registry/uai/components/status-banner.tsx

## Install

```bash
bunx shadcn@latest add https://uaiblocks.dev/r/status-banner.json
```

## Usage

```tsx
"use client";

import { useState } from "react";
import {
  StatusBanner,
  StatusBannerAction,
  StatusBannerActions,
  StatusBannerContent,
  StatusBannerDescription,
  StatusBannerDismiss,
  StatusBannerIcon,
  StatusBannerTitle,
  type StatusBannerVariant,
} from "@/components/ui/uai/status-banner";

export function StatusBannerPreview({ variant = "card" }: { variant?: StatusBannerVariant }) {
  const [maintenanceOpen, setMaintenanceOpen] = useState(true);
  return (
    <div style={{ display: "grid", gap: 12 }}>
      <StatusBanner variant={variant} tone="error">
        <StatusBannerIcon />
        <StatusBannerContent>
          <StatusBannerTitle>Payment failed</StatusBannerTitle>
          <StatusBannerDescription>
            We couldn’t charge the card ending in 4242. Update it by June 12 to keep your seats.
          </StatusBannerDescription>
        </StatusBannerContent>
        <StatusBannerActions>
          <StatusBannerAction>Update card</StatusBannerAction>
        </StatusBannerActions>
      </StatusBanner>
      <StatusBanner variant={variant} tone="success">
        <StatusBannerIcon />
        <StatusBannerContent>
          <StatusBannerTitle>Export ready</StatusBannerTitle>
          <StatusBannerDescription>Q2 invoices.csv · 1,284 rows</StatusBannerDescription>
        </StatusBannerContent>
        <StatusBannerActions>
          <StatusBannerAction>Download</StatusBannerAction>
        </StatusBannerActions>
      </StatusBanner>
      {maintenanceOpen ? (
        <StatusBanner
          variant={variant}
          tone="info"
          open={maintenanceOpen}
          onOpenChange={setMaintenanceOpen}
        >
          <StatusBannerIcon />
          <StatusBannerContent>
            <StatusBannerTitle>Scheduled maintenance</StatusBannerTitle>
            <StatusBannerDescription>
              Sync pauses Saturday from 02:00 to 02:30 UTC. Edits made offline upload afterward.
            </StatusBannerDescription>
          </StatusBannerContent>
          <StatusBannerDismiss />
        </StatusBanner>
      ) : (
        <button
          type="button"
          onClick={() => setMaintenanceOpen(true)}
          style={{
            justifySelf: "start",
            height: 28,
            padding: "0 12px",
            border: 0,
            borderRadius: 999,
            background: "var(--uai-surface-raised)",
            color: "var(--uai-text)",
            fontSize: 12.5,
            fontWeight: 500,
            cursor: "pointer",
          }}
        >
          Show maintenance notice
        </button>
      )}
    </div>
  );
}
```

## Anatomy

- `StatusBanner`
  - `StatusBannerIcon`
  - `StatusBannerContent`
    - `StatusBannerTitle`
    - `StatusBannerDescription`
  - `StatusBannerActions`
    - `StatusBannerAction`
    - `StatusBannerDismiss`

## Accessibility

- Error and warning banners use role="alert"; information and success banners use a polite role="status".
- Tone is conveyed by the title text and icon shape, not color alone; icons are hidden from assistive technology.
- Dismiss is a labelled 28×28 button. Dismissal is controlled or uncontrolled through open and onOpenChange; the consumer decides where focus goes next.
