"use client" import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "../../lib/utils" import { STATUS_BADGE_TONE_CLASS, type StatusBadgeTone, } from "../../lib/status-badge-tints" /** * StatusBadge — centralized chips for product chrome and semantic entity status. * * **Product** (`status`): Beta / New / Alpha on nav, tabs, cards. Uppercase, solid fills. * **Semantic** (`label` + `tone` + `icon`): Published, In review, Draft anywhere in the app. * Use `size="sm"` (default) or `size="md"` for density — not location-specific props. * * Usage: * * * */ export type StatusBadgeProductStatus = | "beta" | "new" | "alpha" | "preview" | "deprecated" export type StatusBadgeSemanticSize = "sm" | "md" /** @deprecated Use `StatusBadgeSemanticSize` */ export type StatusBadgeSurface = "table" | "board" | "detail" /** Default density — tables, lists, filters, inline rows. */ export const STATUS_BADGE_SEMANTIC_SM_SHELL = "inline-flex w-fit shrink-0 items-center gap-1.5 px-2.5 py-1 text-xs font-medium leading-none" /** Roomier density — cards, headers, panels. */ export const STATUS_BADGE_SEMANTIC_MD_SHELL = "inline-flex h-6 min-h-6 w-fit shrink-0 items-center gap-1.5 px-2.5 py-0 text-xs font-medium leading-none border-0 shadow-none" /** @deprecated Use `STATUS_BADGE_SEMANTIC_SM_SHELL` */ export const STATUS_BADGE_TABLE_SHELL = STATUS_BADGE_SEMANTIC_SM_SHELL /** @deprecated Use `STATUS_BADGE_SEMANTIC_MD_SHELL` */ export const STATUS_BADGE_BOARD_SHELL = STATUS_BADGE_SEMANTIC_MD_SHELL /** @deprecated Use `STATUS_BADGE_SEMANTIC_MD_SHELL` */ export const STATUS_BADGE_INSPECTOR_SHELL = STATUS_BADGE_SEMANTIC_MD_SHELL const productStatusBadgeVariants = cva( "inline-flex shrink-0 items-center justify-center font-semibold leading-none tracking-wide uppercase select-none border border-transparent", { variants: { status: { beta: "bg-yellow-400 text-yellow-950 hc:bg-transparent hc:border-foreground hc:text-foreground forced-colors:bg-[Canvas] forced-colors:text-[CanvasText] forced-colors:border-[CanvasText]", new: "bg-brand text-brand-foreground hc:bg-transparent hc:border-foreground hc:text-foreground forced-colors:bg-[Highlight] forced-colors:text-[HighlightText] forced-colors:border-[HighlightText]", alpha: "bg-orange-500 text-white hc:bg-transparent hc:border-foreground hc:text-foreground forced-colors:bg-[Canvas] forced-colors:text-[CanvasText] forced-colors:border-[CanvasText]", preview: "bg-sky-500 text-white hc:bg-transparent hc:border-foreground hc:text-foreground forced-colors:bg-[Canvas] forced-colors:text-[CanvasText] forced-colors:border-[CanvasText]", deprecated: "bg-muted text-muted-foreground border-border hc:border-foreground forced-colors:bg-[Canvas] forced-colors:text-[GrayText] forced-colors:border-[GrayText]", }, size: { xs: "h-4 min-w-4 px-1 text-xs rounded-sm", sm: "h-4 min-w-4 px-1.5 text-xs rounded-full", md: "h-5 min-w-5 px-1.5 text-xs rounded-full", }, variant: { pill: "", dot: "size-2 min-w-0 p-0 rounded-full", }, }, defaultVariants: { status: "beta", size: "sm", variant: "pill", }, }, ) const semanticStatusBadgeVariants = cva("rounded-4xl", { variants: { size: { sm: STATUS_BADGE_SEMANTIC_SM_SHELL, md: STATUS_BADGE_SEMANTIC_MD_SHELL, }, }, defaultVariants: { size: "sm", }, }) const PRODUCT_STATUS_LABEL: Record = { beta: "Beta", new: "New", alpha: "Alpha", preview: "Preview", deprecated: "Deprecated", } function resolveSemanticSize( size?: StatusBadgeSemanticSize, surface?: StatusBadgeSurface, ): StatusBadgeSemanticSize { if (size) return size if (surface === "board" || surface === "detail") return "md" return "sm" } type StatusBadgeBaseProps = Omit, "children"> export type StatusBadgeProductProps = StatusBadgeBaseProps & VariantProps & { status: StatusBadgeProductStatus label?: string tone?: never icon?: never tintClassName?: never surface?: never } export type StatusBadgeSemanticProps = StatusBadgeBaseProps & VariantProps & { label: string /** Font Awesome suffix (e.g. `fa-circle-check`). Shown at sm + md when set. */ icon?: string tone?: StatusBadgeTone tintClassName?: string status?: never variant?: never /** @deprecated Use `size`. Maps table → sm; board | detail → md. */ surface?: StatusBadgeSurface } export type StatusBadgeProps = StatusBadgeProductProps | StatusBadgeSemanticProps export function StatusBadge(props: StatusBadgeProps) { if (props.status === undefined) { const semantic = props as StatusBadgeSemanticProps const { className, label, icon, tone, tintClassName, size, surface, "aria-label": ariaLabel, ...rest } = semantic const resolvedSize = resolveSemanticSize(size ?? undefined, surface) const tint = tintClassName ?? (tone ? STATUS_BADGE_TONE_CLASS[tone] : undefined) return ( {icon ? (