import { useId, type ReactNode } from "react"; import { LogoTile } from "./logo-tile"; import { cn } from "../lib/cn"; /* ---------------------------------------------------------------------------- EmptyState — a designed empty, not an apology (doctrine D5). Every zero-data surface renders this: an optional icon, a short factual title (fragment, no period), ONE orienting sentence (what this area is for or what will appear here), and the primary action to change that — inside the empty state, not off in a distant header. Variants (design brief 7.14). Omitting `variant` keeps the original boxed look, so existing call sites don't change: - "page" (A) centred: 40px icon tile, title, one sentence, one action, 64px from the top. Hide the page header's action while it shows. Pass `templates` for C: 2-3 starter cards that prefill a form. - "inline" (B) one muted sentence and a link, for sections and no results: 'No matches for "aws".' + Clear search. -------------------------------------------------------------------------- */ export type EmptyStateVariant = "boxed" | "page" | "inline"; export function EmptyState({ icon, title, description, action, variant = "boxed", tone = "default", templates, className, }: { icon?: ReactNode | undefined; title: ReactNode; description?: ReactNode | undefined; action?: ReactNode | undefined; /** "boxed" (the original), "page" (A) or "inline" (B). */ variant?: EmptyStateVariant | undefined; /** "danger" colors the icon tile, for load errors. Page variant only. */ tone?: "default" | "danger" | undefined; /** Starter cards under the action (C), usually `EmptyStateTemplates`. Page variant only. */ templates?: ReactNode | undefined; className?: string | undefined; }) { if (variant === "page") { return (
{title}
{description ? ({description}
) : null} {action ? ({title} {description ? <> {description}> : null}
{action ?{title}
{description ? ({description}
) : null} {action ?{label}