import type { ComponentProps } from "react"; import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "./cn"; /* * Promoted 2026-08-11 after NOKL's `Notice` and Enterprise's `Alert` were * compared property by property (see evolution-policy.md). The colors were * already solved — NOKL already bridges to the platform's * `--color-feedback-*` contract (0.11.0+); Enterprise duplicated matching * raw HSL values locally instead of reaching for it. The actual blocker was * the composition model: NOKL took `icon`/`title`/`action` as props on one * element, Enterprise composed ` * ` as a compound component. * * Enterprise's shape won — it already matches how Card and Button compose * (icon as a child, not a prop) — extended with a `NoticeAction` slot * Enterprise never had, since 3 of NOKL's real call sites pass one. * * Two Enterprise bugs fixed in the merge, not carried over: * - `success` was missing entirely, despite the token already existing. * - `destructive` didn't tint its surface or border (`bg-card`, default * border) while `warning`/etc. did, despite `--destructive-muted`/ * `--destructive-border` already existing unused in Enterprise's own * globals.css. * * `role="alert"` over NOKL's `role="note"`: `alert` only triggers screen- * reader announcement on dynamic insertion, so it's a no-op for the many * call sites already present at first paint, and a real signal for the ones * that appear conditionally (a retry banner after an error, a warning after * a fetch resolves). `note` is a landmark role with no live-region behavior * at all — pure downside. * * Colored variants leave `NoticeDescription` without its own text color, so * it inherits the variant's content color from the root by ordinary CSS * cascade — the same "title and body share one tone" behavior NOKL's * version already shipped and called AA-checked in its own comment, rather * than introducing an unverified muted shade. `neutral` is the one variant * that mutes the description, matching Card's own title/description split. */ const noticeVariants = cva( "grid w-full items-start gap-x-3 gap-y-0.5 rounded-lg border px-4 py-3 text-(length:--font-size-control) has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:translate-y-0.5 [&>svg]:text-current", { variants: { variant: { neutral: "border-(color:--color-border) bg-(color:--color-surface-raised) text-(color:--color-content) [&_[data-slot=notice-description]]:text-(color:--color-content-muted)", success: "border-(color:--color-feedback-success-border) bg-(color:--color-feedback-success-surface) text-(color:--color-feedback-success-content)", warning: "border-(color:--color-feedback-warning-border) bg-(color:--color-feedback-warning-surface) text-(color:--color-feedback-warning-content)", info: "border-(color:--color-feedback-info-border) bg-(color:--color-feedback-info-surface) text-(color:--color-feedback-info-content)", destructive: "border-(color:--color-feedback-destructive-border) bg-(color:--color-feedback-destructive-surface) text-(color:--color-feedback-destructive-content)", }, }, defaultVariants: { variant: "neutral", }, }, ); function Notice({ className, variant, ...props }: ComponentProps<"div"> & VariantProps) { return (
); } function NoticeTitle({ className, ...props }: ComponentProps<"div">) { return (
); } function NoticeDescription({ className, ...props }: ComponentProps<"div">) { return (
); } function NoticeAction({ className, ...props }: ComponentProps<"div">) { return (
); } export { Notice, NoticeTitle, NoticeDescription, NoticeAction, noticeVariants };