{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "alert",
  "type": "registry:ui",
  "title": "Alert",
  "description": "Fluent 2 MessageBar-styled alert with shadcn APIs. Three composable parts (Alert, AlertTitle, AlertDescription), five variants (default, destructive, success, warning, info) with subtle intent backgrounds, intent borders, and an optional icon slot.",
  "author": "graundtech <https://github.com/graundtech/fluent2-react-kit>",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "https://fluent2-react-kit.graund.io/r/utils.json"
  ],
  "files": [
    {
      "path": "components/ui/alert.tsx",
      "type": "registry:ui",
      "target": "components/ui/alert.tsx",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport type { ComponentProps } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Alert — Fluent 2-styled (MessageBar look), shadcn-API alert family.\n *\n * Structure matches shadcn/ui's current Alert (three parts: `Alert`,\n * `AlertTitle`, `AlertDescription` — see\n * https://ui.shadcn.com/docs/components/alert): a two-column CSS grid\n * (`grid-cols-[0_1fr]`, collapsing to a real icon column via\n * `has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr]` only when an `<svg>`\n * child is present) so title/description always sit in column 2 and an\n * optional leading icon occupies column 1 without extra markup. No `asChild`\n * — current shadcn doesn't offer one for Alert either.\n *\n * Fluent 2 visual reference: MessageBar\n * (https://storybooks.fluentui.dev/react/?path=/docs/components-messagebar--docs)\n * — a subtle intent-tinted background + intent-colored border + intent-colored\n * icon, with the running body copy staying regular foreground (not tinted).\n * That's a deliberate split from vanilla shadcn's `destructive` variant (which\n * tints the *entire* alert text `text-destructive` and only softens the\n * description). Here only the icon and `AlertTitle` pick up the intent color\n * (via `[&>svg]:text-*` and `*:data-[slot=alert-title]:text-*`);\n * `AlertDescription` always stays `text-muted-foreground` so status is\n * conveyed by icon + border + title color together, never by body-text color\n * alone (accessibility checklist §5).\n *\n * Deviations from current shadcn, both deliberate:\n * - `rounded-md` (Fluent \"medium\", 4px) instead of shadcn's `rounded-lg`.\n *   Per docs/component-conventions.md §3.4, `rounded-md` is this kit's\n *   default *control* radius (buttons, inputs, badges) and `rounded-lg` is\n *   reserved for card/dialog-scale surfaces; an inline notification bar reads\n *   as the former.\n * - `AlertTitle` is `font-semibold` instead of shadcn's `font-medium`, for\n *   consistency with `CardTitle` (also `font-semibold`) elsewhere in this kit.\n *\n * Token usage:\n * - `default`: neutral/Informative — `bg-secondary` (`#f5f5f5` light /\n *   `#333333` dark) with a muted icon, reproducing Fluent's grey-filled\n *   \"Informative\" MessageBar surface (an exact hex match to Figma's\n *   `Status background color`). This is NOT `bg-card`: in light mode `--card`\n *   is `#ffffff`, identical to the page background, so a `bg-card` alert reads\n *   as a bare 1px-bordered box rather than the tinted surface every other\n *   intent (and Fluent's Informative) shows. The border keeps `--border`\n *   (`#d1d1d1`), matching Figma's Informative stroke.\n * - `destructive` / `success` / `warning`: the status-extension tokens\n *   (`*-subtle` background, `*-border` border) added to tokens.css for this\n *   component. `destructive` and `warning` both intentionally accent with a\n *   dedicated `*-text` token instead of the raw status color —\n *   `--destructive`/`--warning` are the *fill* colors (meant for\n *   `Badge`-style filled surfaces with a matching `*-foreground` on top);\n *   as running/title text on a subtle surface neither clears AA in both\n *   themes on its own. `--destructive-text`/`--warning-text` exist\n *   specifically to fix that. Manual sRGB contrast checks against the token\n *   hex values in tokens.css (this environment can't run real axe\n *   color-contrast checks — see the component's test file for why):\n *     - destructive icon/title (`--destructive-text`) vs\n *       `--destructive-subtle`: light `#b10e1c` on `#fdf6f6` ~6.68:1, dark\n *       `#ff9a90` on `#3b1212` ~8.02:1 — both pass AA comfortably. (Plain\n *       `--destructive`, `#d13438` in both themes, was ~4.6:1 light /\n *       ~3.3:1 dark — the dark case failed the 4.5:1 AA body-text minimum,\n *       which is why `--destructive-text` was added at the token layer\n *       rather than re-tuning `--destructive` itself, mirroring how\n *       `--warning-text` sits alongside `--warning`.)\n *     - success icon/title vs `--success-subtle`: light ~5.0:1, dark ~6.5:1\n *       — both pass AA comfortably.\n *     - warning icon/title (`--warning-text`) vs `--warning-subtle`: light\n *       ~5.1:1, dark ~10.6:1 — both pass AA comfortably.\n * - `info`: brand-tinted, using the brand ramp directly since it has no\n *   dedicated status-extension tokens. Light picks `bg-brand-160`\n *   (`#ebf3fc`, the same \"selected nav\" tint `--sidebar-accent` already\n *   uses) with `text-brand-80` (`#0f6cbd`, `= --primary` in light) for the\n *   icon/title — ~4.8:1 against the tint. The brand ramp is global (same hex\n *   in both themes per spec §2), so dark needs explicit overrides:\n *   `dark:bg-brand-30` keeps the tint dark instead of blinding-light, and\n *   `dark:text-brand-100` (not `--primary`'s dark value, `brand-70`, which\n *   only clears ~2.1:1 against `brand-30`) is picked for ~5.0:1 contrast —\n *   `brand-100` is also already `--ring`'s dark-mode color, so it reads as\n *   \"the\" visible accent blue in dark surfaces elsewhere in this kit.\n *   `border-brand-140` / `dark:border-brand-70` sit as a midtone between\n *   each theme's subtle background and accent stop, mirroring how\n *   `*-border` sits between `*-subtle` and the icon/title accent for the\n *   status-extension trio above.\n *\n * Role: `role=\"alert\"` is applied as a *default* — it sits before the\n * `{...props}` spread, so a consumer can override it and a passed\n * `role=\"status\"` wins. Choose deliberately: `role=\"alert\"` is an *assertive*\n * live region (it interrupts the screen reader) and is only *announced* when\n * the alert is mounted dynamically after first paint — a statically-rendered\n * alert present at load isn't announced under either role. Use `role=\"status\"`\n * (polite — queued, not interrupting) for success/info or other non-urgent\n * updates, and keep the assertive default for genuinely urgent/destructive\n * messages. The default stays `role=\"alert\"` (shadcn parity).\n *\n * Server-safe: no `\"use client\"`, no hooks — the React import is type-only.\n */\nconst alertVariants = cva(\n  [\n    \"relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-md border px-4 py-3 text-sm\",\n    \"has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3\",\n    \"[&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n  ],\n  {\n    variants: {\n      variant: {\n        default: \"bg-secondary text-foreground [&>svg]:text-muted-foreground\",\n        destructive:\n          \"bg-destructive-subtle border-destructive-border text-foreground [&>svg]:text-destructive-text *:data-[slot=alert-title]:text-destructive-text\",\n        success:\n          \"bg-success-subtle border-success-border text-foreground [&>svg]:text-success *:data-[slot=alert-title]:text-success\",\n        warning:\n          \"bg-warning-subtle border-warning-border text-foreground [&>svg]:text-warning-text *:data-[slot=alert-title]:text-warning-text\",\n        info: \"bg-brand-160 border-brand-140 text-foreground [&>svg]:text-brand-80 *:data-[slot=alert-title]:text-brand-80 dark:bg-brand-30 dark:border-brand-70 dark:[&>svg]:text-brand-100 dark:*:data-[slot=alert-title]:text-brand-100\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  }\n);\n\nfunction Alert({\n  className,\n  variant = \"default\",\n  ...props\n}: ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n  return (\n    <div\n      data-slot=\"alert\"\n      data-variant={variant}\n      role=\"alert\"\n      className={cn(alertVariants({ variant, className }))}\n      {...props}\n    />\n  );\n}\n\nfunction AlertTitle({ className, ...props }: ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"alert-title\"\n      className={cn(\n        \"col-start-2 line-clamp-1 min-h-4 font-semibold tracking-tight\",\n        className\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction AlertDescription({ className, ...props }: ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"alert-description\"\n      className={cn(\n        \"col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed\",\n        className\n      )}\n      {...props}\n    />\n  );\n}\n\nexport { Alert, AlertTitle, AlertDescription, alertVariants };\n"
    }
  ]
}
