import * as React from "react" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "../../lib/utils" // Each variant is a tone of the shared notice. An explanation is amber, so default, info and warning // share it; there is no blue notice. ALERT_VARIANT_ROLES below is keyed on these names. export const alertVariantClasses = { default: "", destructive: "ak-notice--error", success: "ak-notice--success", warning: "", info: "", } as const export type AlertVariant = keyof typeof alertVariantClasses /** * - HOW URGENTLY EACH VARIANT INTERRUPTS A SCREEN-READER USER. * * `role="alert"` is an ARIA live region with **assertive** semantics: it INTERRUPTS whatever the user * is currently hearing. This component set it unconditionally, for every variant - so * *"No messages in this thread yet."* was announced with the same urgency as *"We couldn't load * conditions."* Correct for a failure; wrong for "there is nothing here". * * made it worse in KIND, not just in count: the meeting window is on screen for an ENTIRE video * visit, and a fresh visit's room thread is legitimately empty - so a routine empty-state alert sat there * for the whole call, beside `CallOverlay`'s genuinely-critical one (a call-lifecycle failure that can * strand someone in a live, billed meeting). **Two competing assertive announcements on one screen, one * of them noise - which is how a user learns to ignore the one that matters.** * * NOT fixed by dropping `role` wholesale. The error variant genuinely needs it. Only the non-error * variants should stop claiming it - they get `status` (polite: announced at the next natural pause). * * A `Record` KEYED ON THE VARIANT NAMES, DELIBERATELY, so a new variant cannot be added without * classifying it. That matters right now: is mid-sweep on this file and adds `warning` and * `info`. When those land, this map must gain entries or TypeScript names them - and because the plugin * has no type gate, `alert.test.tsx` asserts the same thing at RUNTIME so the suite catches it * too. Silently inheriting `alert` is exactly what this card exists to stop. * Judgement for the two incoming ones, recorded so it is not re-derived: `warning` and `info` are both * `status` - a warning is not a failure the user must act on this instant, and info never is. */ export const ALERT_VARIANT_ROLES: Record = { default: "status", destructive: "alert", success: "status", // two landed in the same merge cycle that brought this map in. Classified per the // judgement recorded above rather than re-derived: neither is a failure demanding this instant. warning: "status", info: "status", } const alertVariants = cva("ak-notice relative", { variants: { variant: alertVariantClasses, }, defaultVariants: { variant: "default", }, }) function Alert({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps) { return (
) } function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { return (
) } function AlertDescription({ className, ...props }: React.ComponentProps<"div">) { return (
) } export { Alert, AlertTitle, AlertDescription }