# Status Banner

> Alert-style status banner with tabs support and timestamp display

A shadcn/ui block from the [@openstatus](https://openstatus.dev/registry) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/openstatus/status-banner).

- Page, with a live preview: https://shadcn.exchange/r/openstatus/status-banner
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/openstatus/status-banner-light-356400374f7ccbbd.png
- Registry item: https://openstatus.dev/r/status-banner.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

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

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `https://openstatus.dev/r/status-icon.json`, `https://openstatus.dev/r/status-types.json`, `https://openstatus.dev/r/status-utils.json`, `https://openstatus.dev/r/status-timestamp.json`, `https://openstatus.dev/r/status-i18n.json`, `tabs`

## Files

### `src/components/blocks/status-banner.tsx`

````tsx
"use client";

import { useStatusBlocksLabels } from "@/components/blocks/status-i18n";
import { StatusIcon as UnifiedStatusIcon } from "@/components/blocks/status-icon";
import { StatusTimestamp } from "@/components/blocks/status-timestamp";
import type { StatusType } from "@/components/blocks/status.types";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@/components/ui/tabs";
import { cn } from "@/lib/utils";

/**
 * StatusBanner - Complete banner component with integrated icon, message, and timestamp
 *
 * A fully composed banner component that displays a prominent status message with:
 * - Status-colored icon on the left
 * - Automatic status message (e.g., "All Systems Operational")
 * - Current timestamp on the right
 *
 * The banner automatically styles itself based on the status type with colored
 * backgrounds and borders. This is the simplest way to display a status banner
 * when you don't need custom content.
 *
 * For custom banner content, use StatusBannerContainer with manual composition.
 *
 * @param status - The status type that determines appearance and message
 *
 * @example
 * ```tsx
 * <StatusBanner status="success" />
 * // Displays: [✓ icon] All Systems Operational | Jan 15, 2024 10:30 (UTC)
 * ```
 *
 * @example
 * ```tsx
 * <StatusBanner status="degraded" />
 * // Displays: [⚠ icon] Degraded Performance | Jan 15, 2024 10:30 (UTC)
 * ```
 *
 * @see StatusBannerContainer - For custom banner composition
 * @see StatusBannerMessage - For the automatic status message
 * @see StatusTimestamp - For the timestamp display
 */
export function StatusBanner({
  className,
  status,
}: React.ComponentProps<"div"> & {
  status?: Exclude<StatusType, "empty">;
}) {
  return (
    <StatusBannerContainer
      status={status}
      className={cn(
        "flex items-center gap-3 px-3 py-2 sm:px-4 sm:py-3",
        "data-[status=success]:bg-success/20",
        "data-[status=degraded]:bg-warning/20",
        "data-[status=error]:bg-destructive/20",
        "data-[status=info]:bg-info/20",
        className,
      )}
    >
      <StatusBannerIcon className="flex-shrink-0" />
      <div className="flex flex-1 flex-wrap items-center justify-between gap-2">
        <StatusBannerMessage className="text-xl font-semibold" />
        <StatusTimestamp date={new Date()} className="text-xs" />
      </div>
    </StatusBannerContainer>
  );
}
StatusBanner.displayName = "StatusBanner";

/**
 * StatusBannerContainer - Base container for status banner composition
 *
 * Provides a rounded, bordered container with status-based styling via data
 * attributes. The container acts as a CSS group (/status-banner) enabling child
 * components to style themselves based on the status type.
 *
 * Background colors automatically adjust for light/dark mode:
 * - success: Green tint (bg-success/5 light, bg-success/10 dark)
 * - degraded: Yellow tint (bg-warning/5 light, bg-warning/10 dark)
 * - error: Red tint (bg-destructive/5 light, bg-destructive/10 dark)
 * - info: Blue tint (bg-info/5 light, bg-info/10 dark)
 *
 * @param status - The status type for styling
 *
 * @example
 * ```tsx
 * <StatusBannerContainer status="error">
 *   <StatusBannerTitle>Active Incident</StatusBannerTitle>
 *   <StatusBannerContent>
 *     <p>We are experiencing issues with the API.</p>
 *   </StatusBannerContent>
 * </StatusBannerContainer>
 * ```
 *
 * @see StatusBanner - For a pre-composed banner with icon/message/timestamp
 * @see StatusBannerTitle - For colored title bar
 * @see StatusBannerContent - For main content area
 */
export function StatusBannerContainer({
  className,
  children,
  status,
}: React.ComponentProps<"div"> & {
  status?: Exclude<StatusType, "empty">;
}) {
  return (
    <div
      data-slot="status-banner"
      data-status={status}
      className={cn(
        "group/status-banner overflow-hidden rounded-lg border",
        "data-[status=success]:border-success data-[status=success]:bg-success/5 dark:data-[status=success]:bg-success/10",
        "data-[status=degraded]:border-warning data-[status=degraded]:bg-warning/5 dark:data-[status=degraded]:bg-warning/10",
        "data-[status=error]:border-destructive data-[status=error]:bg-destructive/5 dark:data-[status=error]:bg-destructive/10",
        "data-[status=info]:border-info data-[status=info]:bg-info/5 dark:data-[status=info]:bg-info/10",
        className,
      )}
    >
      {children}
    </div>
  );
}
StatusBannerContainer.displayName = "StatusBannerContainer";

/**
 * StatusBannerMessage - Automatic status message display
 *
 * Displays a status message that automatically shows the appropriate text based
 * on the parent StatusBannerContainer's status. Uses CSS data attribute selectors
 * to show only the relevant message:
 * - success: "All Systems Operational"
 * - degraded: "Degraded Performance"
 * - error: "Partial Outage"
 * - info: "Maintenance"
 *
 * The messages are sourced from systemStatusLabels.long for consistent messaging.
 *
 * @example
 * ```tsx
 * <StatusBannerContainer status="success">
 *   <StatusBannerMessage className="text-xl font-semibold" />
 *   // Displays "All Systems Operational"
 * </StatusBannerContainer>
 * ```
 *
 * @see StatusBannerContainer - For setting the status context
 * @see systemStatusLabels - For the message text definitions
 */
export function StatusBannerMessage({
  className,
  ...props
}: React.ComponentProps<"div">) {
  const labels = useStatusBlocksLabels();
  return (
    <div className={cn(className)} {...props}>
      <span className="hidden group-data-[status=success]/status-banner:block">
        {labels.systemStatus.success.long}
      </span>
      <span className="hidden group-data-[status=degraded]/status-banner:block">
        {labels.systemStatus.degraded.long}
      </span>
      <span className="hidden group-data-[status=error]/status-banner:block">
        {labels.systemStatus.error.long}
      </span>
      <span className="hidden group-data-[status=info]/status-banner:block">
        {labels.systemStatus.info.long}
      </span>
    </div>
  );
}

/**
 * StatusBannerTitle - Colored title bar for banner sections
 *
 * Displays a title with a solid status-colored background and light text color.
 * The background color automatically adjusts based on the parent StatusBannerContainer's
 * status type:
 * - success: Green background
 * - degraded: Yellow background
 * - error: Red background
 * - info: Blue background
 *
 * Typically used to create distinct sections within a banner or to highlight
 * important information.
 *
 * @example
 * ```tsx
 * <StatusBannerContainer status="error">
 *   <StatusBannerTitle>Ongoing Incident</StatusBannerTitle>
 *   <StatusBannerContent>
 *     <p>Details about the incident...</p>
 *   </StatusBannerContent>
 * </StatusBannerContainer>
 * ```
 *
 * @see StatusBannerContainer - For setting the status context
 * @see StatusBannerContent - For main content below the title
 */
export function StatusBannerTitle({
  className,
  children,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <div
      className={cn(
        "text-background px-3 py-2 font-medium",
        "group-data-[status=success]/status-banner:bg-success",
        "group-data-[status=degraded]/status-banner:bg-warning",
        "group-data-[status=error]/status-banner:bg-destructive",
        "group-data-[status=info]/status-banner:bg-info",
        className,
      )}
      {...props}
    >
      {children}
    </div>
  );
}
StatusBannerTitle.displayName = "StatusBannerTitle";

/**
 * StatusBannerContent - Main content area for banner messages
 *
 * Provides consistent padding and spacing (gap-2) for banner content. Used to
 * display detailed messages, updates, or other information within a status banner.
 *
 * The padding is responsive: px-3 py-2 on mobile, px-4 py-3 on larger screens.
 *
 * @example
 * ```tsx
 * <StatusBannerContainer status="info">
 *   <StatusBannerTitle>Scheduled Maintenance</StatusBannerTitle>
 *   <StatusBannerContent>
 *     <p>We will be performing maintenance on Jan 20 from 2-4 AM UTC.</p>
 *     <p>Some services may be temporarily unavailable.</p>
 *   </StatusBannerContent>
 * </StatusBannerContainer>
 * ```
 *
 * @see StatusBannerContainer - For the container
 * @see StatusBannerTitle - For optional title bar above content
 */
export function StatusBannerContent({
  className,
  children,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <div
      className={cn("flex flex-col gap-2 px-3 py-2 sm:px-4 sm:py-3", className)}
      {...props}
    >
      {children}
    </div>
  );
}
StatusBannerContent.displayName = "StatusBannerContent";

/**
 * StatusBannerIcon - Status indicator icon for banner context
 *
 * This component wraps the unified StatusIcon with variant="banner", configuring
 * it to respond to the parent StatusBannerContainer's data-status attribute.
 * The displayed icon automatically changes based on the status type:
 * - success: CheckIcon
 * - degraded: TriangleAlertIcon
 * - error: AlertCircleIcon
 * - info: WrenchIcon
 *
 * @example
 * ```tsx
 * <StatusBannerContainer status="degraded">
 *   <div className="flex items-center gap-3">
 *     <StatusBannerIcon />
 *     <StatusBannerMessage />
 *   </div>
 * </StatusBannerContainer>
 * ```
 *
 * @see StatusBannerContainer - For setting the status context
 * @see StatusIcon from status-icon.tsx - For the underlying unified icon implementation
 */
export function StatusBannerIcon({
  className,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <UnifiedStatusIcon variant="banner" className={className} {...props} />
  );
}
StatusBannerIcon.displayName = "StatusBannerIcon";

// ============================================================================
// Tab Components
// ============================================================================

/**
 * StatusBannerTabs - Tab container for multi-section status banners
 *
 * Provides a tabbed interface for status banners, allowing multiple views or
 * sections within a single banner. The tabs container automatically applies
 * status-based background colors matching the banner theme.
 *
 * Built on Radix UI Tabs with status-aware styling.
 *
 * @param status - The status type for background color theming
 *
 * @example
 * ```tsx
 * <StatusBannerTabs status="degraded" defaultValue="impact">
 *   <StatusBannerTabsList>
 *     <StatusBannerTabsTrigger value="impact" status="degraded">
 *       Impact
 *     </StatusBannerTabsTrigger>
 *     <StatusBannerTabsTrigger value="updates" status="degraded">
 *       Updates
 *     </StatusBannerTabsTrigger>
 *   </StatusBannerTabsList>
 *   <StatusBannerTabsContent value="impact">
 *     <StatusBannerContent>
 *       <p>Services affected by this incident...</p>
 *     </StatusBannerContent>
 *   </StatusBannerTabsContent>
 *   <StatusBannerTabsContent value="updates">
 *     <StatusBannerContent>
 *       <p>Latest updates on resolution...</p>
 *     </StatusBannerContent>
 *   </StatusBannerTabsContent>
 * </StatusBannerTabs>
 * ```
 *
 * @see StatusBannerTabsList - For the tab navigation
 * @see StatusBannerTabsTrigger - For individual tab buttons
 * @see StatusBannerTabsContent - For tab panel content
 */
export function StatusBannerTabs({
  className,
  children,
  status,
  ...props
}: React.ComponentProps<typeof Tabs> & {
  status?: Exclude<StatusType, "empty">;
}) {
  return (
    <Tabs
      data-slot="status-banner-tabs"
      data-status={status}
      className={cn(
        "gap-0",
        "data-[status=success]:bg-success/20",
        "data-[status=degraded]:bg-warning/20",
        "data-[status=error]:bg-destructive/20",
        "data-[status=info]:bg-info/20",
        className,
      )}
      {...props}
    >
      {children}
    </Tabs>
  );
}

/**
 * StatusBannerTabsList - Tab navigation container
 *
 * Wraps the tab triggers in a scrollable container with rounded top corners.
 * The container automatically handles overflow with horizontal scrolling on
 * smaller screens.
 *
 * @example
 * ```tsx
 * <StatusBannerTabsList>
 *   <StatusBannerTabsTrigger value="overview" status="success">
 *     Overview
 *   </StatusBannerTabsTrigger>
 *   <StatusBannerTabsTrigger value="details" status="success">
 *     Details
 *   </StatusBannerTabsTrigger>
 * </StatusBannerTabsList>
 * ```
 *
 * @see StatusBannerTabsTrigger - For individual tab buttons
 */
export function StatusBannerTabsList({
  className,
  children,
  ...props
}: React.ComponentProps<typeof TabsList>) {
  return (
    <div className={cn("rounded-t-lg", "w-full overflow-x-auto")}>
      <TabsList
        className={cn(
          "rounded-none rounded-t-lg p-0",
          "border-none",
          className,
        )}
        {...props}
      >
        {children}
      </TabsList>
    </div>
  );
}

/**
 * StatusBannerTabsTrigger - Individual tab button
 *
 * Displays a single tab trigger button with status-based coloring. The button
 * shows:
 * - Inactive state: 50% opacity status color background
 * - Active state: Full status color background with light text
 *
 * The status parameter should match the parent StatusBannerTabs status for
 * consistent theming.
 *
 * @param status - The status type for color theming
 * @param value - The tab value (for Radix UI Tabs)
 *
 * @example
 * ```tsx
 * <StatusBannerTabsList>
 *   <StatusBannerTabsTrigger value="affected" status="error">
 *     Affected Services
 *   </StatusBannerTabsTrigger>
 *   <StatusBannerTabsTrigger value="timeline" status="error">
 *     Timeline
 *   </StatusBannerTabsTrigger>
 * </StatusBannerTabsList>
 * ```
 *
 * @see StatusBannerTabsList - For the container
 * @see StatusBannerTabsContent - For the corresponding content panels
 */
export function StatusBannerTabsTrigger({
  className,
  children,
  status,
  ...props
}: React.ComponentProps<typeof TabsTrigger> & {
  status?: Exclude<StatusType, "empty">;
}) {
  return (
    <TabsTrigger
      data-slot="status-banner-tabs-trigger"
      data-status={status}
      className={cn(
        "font-mono",
        "rounded-none border-none focus-visible:ring-inset",
        "text-foreground data-[state=active]:text-background dark:text-foreground dark:data-[state=active]:text-background h-full",
        "data-[state=active]:data-[status=success]:bg-success data-[status=success]:bg-success/50 dark:data-[state=active]:data-[status=success]:bg-success dark:data-[status=success]:bg-success/50",
        "data-[state=active]:data-[status=degraded]:bg-warning data-[status=degraded]:bg-warning/50 dark:data-[state=active]:data-[status=degraded]:bg-warning dark:data-[status=degraded]:bg-warning/50",
        "data-[state=active]:data-[status=error]:bg-destructive data-[status=error]:bg-destructive/50 dark:data-[state=active]:data-[status=error]:bg-destructive dark:data-[status=error]:bg-destructive/50",
        "data-[state=active]:data-[status=info]:bg-info data-[status=info]:bg-info/50 dark:data-[state=active]:data-[status=info]:bg-info dark:data-[status=info]:bg-info/50",
        "data-[state=active]:shadow-none",
        className,
      )}
      {...props}
    >
      {children}
    </TabsTrigger>
  );
}

/**
 * StatusBannerTabsContent - Tab panel content container
 *
 * Wraps the content for a single tab panel. The component includes negative
 * horizontal margin (-mx-3) to align edge-to-edge with the banner container
 * when used with StatusBannerContent.
 *
 * @param value - The tab value (must match a StatusBannerTabsTrigger value)
 *
 * @example
 * ```tsx
 * <StatusBannerTabsContent value="updates">
 *   <StatusBannerContent>
 *     <h3>Latest Update</h3>
 *     <p>We have identified the issue and are working on a fix...</p>
 *   </StatusBannerContent>
 * </StatusBannerTabsContent>
 * ```
 *
 * @see StatusBannerTabsTrigger - For the tab button that activates this content
 * @see StatusBannerContent - Typically used as a child for proper padding
 */
export function StatusBannerTabsContent({
  className,
  children,
  ...props
}: React.ComponentProps<typeof TabsContent>) {
  return (
    <TabsContent className={cn("-mx-3", className)} {...props}>
      {children}
    </TabsContent>
  );
}
````
