Banner

Inline status message pairing a Lucide icon with tone (icon + colour, never colour alone).

import { Banner }from "@/components/ui"

Specification

Shows an inline, page-spanning status message pairing a Lucide icon with a tone and an optional action.

Props (5)
Every prop this component accepts, its type, default, and how to use it.
PropTypeDefaultDescription
tone*"amber" | "rose" | "neutral"—Sets the semantic color of the banner (never rely on color alone — always pair with an icon).
icon*LucideIcon—Leading icon that reinforces the message's meaning.
children*ReactNode—The banner message content.
actionstring—Label for an optional inline action button.
onAction() => void—Handler invoked when the action button is clicked.

Tones with action

3 invoices need your approval.
Showing results from the last 30 days.
Full source
The complete component, read from src/components/ui/banner.tsx.
banner.tsx
"use client";

import { type ReactNode } from "react";
import type { LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";

type BannerTone = "amber" | "rose" | "neutral";

interface BannerProps {
  tone: BannerTone;
  icon: LucideIcon;
  children: ReactNode;
  action?: string;
  onAction?: () => void;
}

const TONE_CLASS: Record<BannerTone, string> = {
  amber: "bg-warning-light text-warning",
  rose: "bg-error-light text-error",
  neutral: "bg-bg-secondary text-text-secondary",
};

export function Banner({ tone, icon: Icon, children, action, onAction }: BannerProps) {
  return (
    <div
      role="status"
      className={cn(
        "flex flex-wrap items-center gap-2 border-b border-border px-4 py-2.5 text-sm",
        TONE_CLASS[tone]
      )}
    >
      <Icon size={15} className="shrink-0" aria-hidden />
      <span className="flex-1">{children}</span>
      {action && (
        <button
          onClick={onAction}
          className="rounded px-2 py-0.5 text-sm font-medium underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-current"
        >
          {action}
        </button>
      )}
    </div>
  );
}