{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"alert","type":"registry:ui","title":"Alert","description":"A callout that draws attention to important information.","dependencies":["lucide-react"],"registryDependencies":["https://dashral.com/r/utils.json"],"files":[{"path":"registry/dashral/alert.tsx","type":"registry:file","target":"components/dashral/alert.tsx","content":"import * as React from \"react\"\nimport { CircleAlert, CircleCheck, Info, Sparkles, TriangleAlert, XIcon } from \"lucide-react\"\n\nimport { cn } from \"./lib/utils\"\n\ntype AlertVariant = \"soft\" | \"outline\" | \"solid\"\ntype AlertColor = \"neutral\" | \"primary\" | \"info\" | \"success\" | \"warning\" | \"destructive\" | \"highlight\"\n\n// Every class is written out in full so Tailwind finds it. The description takes the text color, a little softer.\nconst tones: Record<AlertVariant, Record<AlertColor, string>> = {\n  soft: {\n    neutral: \"bg-muted/50 text-foreground **:data-[slot=alert-body]:text-muted-foreground\",\n    primary: \"border-primary/30 bg-primary/8 text-primary-text **:data-[slot=alert-body]:text-primary-text/90\",\n    info: \"border-info/30 bg-info/8 text-info-text **:data-[slot=alert-body]:text-info-text/90\",\n    success: \"border-success/30 bg-success/8 text-success-text **:data-[slot=alert-body]:text-success-text/90\",\n    warning: \"border-warning/40 bg-warning/10 text-warning-text **:data-[slot=alert-body]:text-warning-text/90\",\n    destructive: \"border-destructive/30 bg-destructive/8 text-destructive-text **:data-[slot=alert-body]:text-destructive-text/90\",\n    highlight: \"border-highlight/30 bg-highlight/8 text-highlight-text **:data-[slot=alert-body]:text-highlight-text/90\",\n  },\n  outline: {\n    neutral: \"bg-card text-card-foreground **:data-[slot=alert-body]:text-muted-foreground\",\n    primary: \"border-primary/40 bg-card text-primary-text **:data-[slot=alert-body]:text-muted-foreground\",\n    info: \"border-info/40 bg-card text-info-text **:data-[slot=alert-body]:text-muted-foreground\",\n    success: \"border-success/40 bg-card text-success-text **:data-[slot=alert-body]:text-muted-foreground\",\n    warning: \"border-warning/50 bg-card text-warning-text **:data-[slot=alert-body]:text-muted-foreground\",\n    destructive: \"border-destructive/40 bg-card text-destructive-text **:data-[slot=alert-body]:text-muted-foreground\",\n    highlight: \"border-highlight/40 bg-card text-highlight-text **:data-[slot=alert-body]:text-muted-foreground\",\n  },\n  solid: {\n    neutral: \"border-transparent bg-foreground text-background **:data-[slot=alert-body]:text-background/85\",\n    primary: \"border-transparent bg-primary text-primary-foreground **:data-[slot=alert-body]:text-primary-foreground/85\",\n    info: \"border-transparent bg-info text-info-foreground **:data-[slot=alert-body]:text-info-foreground/85\",\n    success: \"border-transparent bg-success text-success-foreground **:data-[slot=alert-body]:text-success-foreground/85\",\n    warning: \"border-transparent bg-warning text-warning-foreground **:data-[slot=alert-body]:text-warning-foreground/85\",\n    destructive: \"border-transparent bg-destructive text-destructive-foreground **:data-[slot=alert-body]:text-destructive-foreground/85\",\n    highlight: \"border-transparent bg-highlight text-highlight-foreground **:data-[slot=alert-body]:text-highlight-foreground/85\",\n  },\n}\n\nconst defaultIcons: Record<AlertColor, React.ReactNode> = {\n  neutral: <Info />,\n  primary: <Info />,\n  info: <Info />,\n  success: <CircleCheck />,\n  warning: <TriangleAlert />,\n  destructive: <CircleAlert />,\n  highlight: <Sparkles />,\n}\n\ntype AlertProps = Omit<React.ComponentProps<\"div\">, \"title\" | \"color\"> & {\n  title?: React.ReactNode\n  description?: React.ReactNode\n  /** How much it stands out: soft (default), outline or solid. */\n  variant?: AlertVariant\n  /** What it means. Neutral by default. */\n  color?: AlertColor\n  /** Replaces the color's icon; false shows none. */\n  icon?: React.ReactNode | false\n  /** At the end, e.g. a button: \"Retry\", \"Upgrade\". */\n  action?: React.ReactNode\n  /** Shows a close button, and is called when it's pressed. */\n  onClose?: () => void\n  /** The close button's name for screen readers, in your language. */\n  closeLabel?: string\n  classNames?: { icon?: string; title?: string; description?: string; action?: string }\n}\n\n/**\n * A message on the page, in one tag: a title and description, an icon that fits the color, and optionally an action\n * and a close button. Anything in children goes under the description. Warnings and errors are announced.\n */\nfunction Alert({\n  title,\n  description,\n  variant = \"soft\",\n  color = \"neutral\",\n  icon,\n  action,\n  onClose,\n  closeLabel = \"Dismiss\",\n  className,\n  classNames,\n  children,\n  ...props\n}: AlertProps) {\n  const shownIcon = icon === false ? null : (icon ?? defaultIcons[color])\n  return (\n    <div\n      data-slot=\"alert\"\n      role={color === \"destructive\" || color === \"warning\" ? \"alert\" : \"status\"}\n      className={cn(\"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-sm\", tones[variant][color], className)}\n      {...props}\n    >\n      {shownIcon && (\n        <span aria-hidden className={cn(\"flex shrink-0 translate-y-0.5 [&_svg]:size-4\", classNames?.icon)}>\n          {shownIcon}\n        </span>\n      )}\n      <div className=\"grid min-w-0 flex-1 gap-0.5\">\n        {title && <div className={cn(\"font-medium tracking-tight\", classNames?.title)}>{title}</div>}\n        {(description || children) && (\n          <div data-slot=\"alert-body\" className={cn(\"grid justify-items-start gap-2 [&_p]:leading-relaxed\", classNames?.description)}>\n            {description && <div>{description}</div>}\n            {children}\n          </div>\n        )}\n      </div>\n      {action && <div className={cn(\"flex shrink-0 items-center gap-2 self-center\", classNames?.action)}>{action}</div>}\n      {onClose && (\n        <button\n          type=\"button\"\n          aria-label={closeLabel}\n          onClick={onClose}\n          className=\"-me-1 flex size-6 shrink-0 items-center justify-center rounded-md opacity-70 outline-none transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-ring/50 [&_svg]:size-4\"\n        >\n          <XIcon aria-hidden />\n        </button>\n      )}\n    </div>\n  )\n}\n\nexport { Alert, type AlertProps, type AlertVariant, type AlertColor }\n"}],"cssVars":{"theme":{"color-primary-text":"var(--primary-text, var(--primary))","color-destructive-foreground":"var(--destructive-foreground)","color-destructive-text":"var(--destructive-text)","color-info":"var(--info)","color-info-foreground":"var(--info-foreground)","color-info-text":"var(--info-text)","color-success":"var(--success)","color-success-foreground":"var(--success-foreground)","color-success-text":"var(--success-text)","color-warning":"var(--warning)","color-warning-foreground":"var(--warning-foreground)","color-warning-text":"var(--warning-text)","color-highlight":"var(--highlight)","color-highlight-foreground":"var(--highlight-foreground)","color-highlight-text":"var(--highlight-text)"},"light":{"destructive-foreground":"oklch(0.985 0 0)","destructive-text":"#bd2800","info":"oklch(0.5 0.134 242.749)","info-foreground":"oklch(0.985 0 0)","info-text":"oklch(0.443 0.11 240.79)","success":"oklch(0.508 0.118 165.612)","success-foreground":"oklch(0.985 0 0)","success-text":"oklch(0.432 0.095 166.913)","warning":"#f59200","warning-foreground":"oklch(0.3 0.07 60)","warning-text":"#964e00","highlight":"#b8008c","highlight-foreground":"oklch(0.985 0 0)","highlight-text":"#a3007b"},"dark":{"destructive-foreground":"oklch(0.2 0 0)","destructive-text":"#ff8a5c","info":"oklch(0.685 0.169 237.323)","info-foreground":"oklch(0.2 0 0)","info-text":"oklch(0.746 0.16 232.661)","success":"oklch(0.696 0.17 162.48)","success-foreground":"oklch(0.2 0.04 160)","success-text":"oklch(0.765 0.177 163.223)","warning":"#f59200","warning-foreground":"oklch(0.25 0.06 60)","warning-text":"#ffba42","highlight":"#ff2ecf","highlight-foreground":"oklch(0.2 0 0)","highlight-text":"#ff75df"}}}