| 1 | /** |
| 2 | * State is a mark and a word, never colour alone. |
| 3 | * |
| 4 | * <Status> is the general form: a dot in the tone's colour and the word in |
| 5 | * text. `live` lights its dot (bioluminescence) and is only for something |
| 6 | * the site actually observes; nothing static qualifies. |
| 7 | * |
| 8 | * <StatusBadge> keeps the older availability vocabulary (experimental, |
| 9 | * preview, pending, unavailable) for the pages that still use it. |
| 10 | */ |
| 11 | |
| 12 | import type { ReactNode } from "react"; |
| 13 | import type { LocalizedText } from "@/lib/content/vocabulary"; |
| 14 | import { pickText } from "@/lib/i18n/dictionaries"; |
| 15 | |
| 16 | export type StatusTone = "ready" | "attention" | "idle" | "live" | "danger" | "accent"; |
| 17 | |
| 18 | export function Status({ tone, children }: { tone: StatusTone; children: ReactNode }) { |
| 19 | return ( |
| 20 | <span className={`status status-${tone}`}> |
| 21 | <span className="status-dot" aria-hidden="true" /> |
| 22 | {children} |
| 23 | </span> |
| 24 | ); |
| 25 | } |
| 26 | |
| 27 | export type StatusKind = "experimental" | "preview" | "pending" | "unavailable"; |
| 28 | |
| 29 | const DEFAULT_LABELS: Record<StatusKind, LocalizedText> = { |
| 30 | experimental: { en: "Experimental", zh: "实验性" }, |
| 31 | preview: { en: "Preview", zh: "预览" }, |
| 32 | pending: { en: "Pending", zh: "待就绪" }, |
| 33 | unavailable: { en: "Unavailable", zh: "暂不可用" }, |
| 34 | }; |
| 35 | |
| 36 | export function StatusBadge({ |
| 37 | kind, |
| 38 | locale = "en", |
| 39 | label, |
| 40 | }: { |
| 41 | kind: StatusKind; |
| 42 | locale?: string; |
| 43 | /** Overrides the default per-kind label (e.g. a media entry's pendingLabel). */ |
| 44 | label?: LocalizedText; |
| 45 | }) { |
| 46 | const text = pickText(label ?? DEFAULT_LABELS[kind], locale); |
| 47 | |
| 48 | return ( |
| 49 | <span className={`status-badge status-badge-${kind}`}> |
| 50 | <span className="status-badge-dot" aria-hidden="true" /> |
| 51 | {text} |
| 52 | </span> |
| 53 | ); |
| 54 | } |
| 55 |