{
  "schemaVersion": 1,
  "name": "toast",
  "useFor": "Prefer Sonner for new work. Use this when an app already uses the toast() and useToast() API: mount one Toaster near the root, call toast({ title, description, action }) and use variant=\"destructive\" for a failure. Give an action an altText that says what it does.",
  "constraints": [
    "A toast for an error that needs a decision (use an alert dialog)",
    "More than one action",
    "Long descriptions"
  ],
  "documentation": "",
  "source": "Extension from opencommerce-agentcard-web src/components (the order card's done step) and sonner.tsx",
  "exports": [
    "Toast",
    "ToastAction",
    "ToastClose",
    "ToastDescription",
    "Toaster",
    "ToastProvider",
    "ToastTitle",
    "ToastViewport",
    "toast",
    "useToast",
    "ToastActionElement",
    "ToastProps"
  ],
  "client": true,
  "docsUrl": "https://opencommerce-ds.vercel.app/components/toast",
  "markdownUrl": "https://opencommerce-ds.vercel.app/r/toast.md",
  "examples": [
    {
      "path": "examples/toast.tsx",
      "content": "\"use client\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { ToastAction, Toaster, toast } from \"@/components/ui/toast\";\n\nexport function Site() {\n  return (\n    <div className=\"flex flex-wrap gap-3\">\n      <Button\n        variant=\"secondary\"\n        onClick={() =>\n          toast({\n            title: \"Order placed\",\n            description: \"ord_8KQ2 at Northwind Outfitters\",\n            action: (\n              <ToastAction altText=\"Open the order\" onClick={() => undefined}>\n                Open\n              </ToastAction>\n            ),\n          })\n        }\n      >\n        Place order\n      </Button>\n      <Button\n        variant=\"secondary\"\n        onClick={() =>\n          toast({\n            variant: \"destructive\",\n            title: \"Checkout failed\",\n            description: \"The card was declined\",\n            action: <ToastAction altText=\"Retry the checkout\">Retry</ToastAction>,\n          })\n        }\n      >\n        Fail a checkout\n      </Button>\n      <Button variant=\"ghost\" onClick={() => toast({ title: \"Copied ord_8KQ2\" })}>\n        Copy order ID\n      </Button>\n      <Toaster />\n    </div>\n  );\n}\n",
      "exports": [
        "Site"
      ],
      "requires": [
        "toast",
        "button"
      ],
      "packages": [],
      "previews": [
        {
          "name": "Site",
          "url": "https://opencommerce-ds.vercel.app/preview/toast/Site"
        }
      ]
    }
  ],
  "type": "ui",
  "title": "Toast",
  "description": "The older Radix toast in the look of the brand's Sonner toasts: a white card at the bottom left with a blue action.",
  "surface": "site",
  "kinds": [],
  "requires": [
    "theme",
    "utils"
  ],
  "packages": [
    "@radix-ui/react-toast",
    "class-variance-authority",
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/ui/toast.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\n// The Radix toast (shadcn's older toast API; prefer Sonner for new work), in the same look as the brand's Sonner toasts\n// (sonner.tsx): a white card at the bottom left, a 9 percent ink edge, 8px corners and a soft drop, the title in 14px\n// Inter at 500 over its line in 12px at 64 percent ink, an action as a small blue key and a faint close mark.\n// `destructive` edges it in red with a red title and a red key. It slides in from the left edge it lives on as it\n// fades (300ms ease-out); a swipe to the left drags it with the finger and lets it go, a short swipe springs back\n// (200ms ease-out). Reduced motion keeps only the fade.\nconst ToastProvider = ToastPrimitive.Provider;\n\nfunction ToastViewport({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Viewport>) {\n  return (\n    <ToastPrimitive.Viewport\n      data-slot=\"toast-viewport\"\n      className={cn(\"fixed bottom-0 left-0 z-100 flex max-h-dvh w-full flex-col-reverse gap-2 p-4.5 outline-none sm:max-w-sm sm:pb-5 sm:pl-7.5\", className)}\n      {...props}\n    />\n  );\n}\n\nconst toastVariants = cva(\n  \"group/toast pointer-events-auto relative flex w-full items-center justify-between gap-3 overflow-hidden rounded-control border border-line bg-surface py-3 pr-10 pl-3.5 font-sans text-fg shadow-floating transition-[translate,opacity] duration-300 ease-out starting:-translate-x-4 starting:opacity-0 data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:duration-200 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=end]:opacity-0 data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none motion-reduce:starting:translate-x-0\",\n  {\n    variants: {\n      variant: {\n        default: \"\",\n        destructive: \"border-danger [&_[data-slot=toast-title]]:text-danger\",\n      },\n    },\n    defaultVariants: { variant: \"default\" },\n  },\n);\n\nfunction Toast({ className, variant, ...props }: React.ComponentProps<typeof ToastPrimitive.Root> & VariantProps<typeof toastVariants>) {\n  return <ToastPrimitive.Root data-slot=\"toast\" data-variant={variant ?? \"default\"} className={cn(toastVariants({ variant }), className)} {...props} />;\n}\n\nfunction ToastAction({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Action>) {\n  return (\n    <ToastPrimitive.Action\n      data-slot=\"toast-action\"\n      className={cn(\n        \"inline-flex h-7 shrink-0 items-center justify-center rounded-sm border border-line-brand-edge bg-primary px-2.5 font-sans text-caption font-medium text-on-primary outline-none transition-[background-color,scale] duration-160 ease-out hover:bg-primary-hover active:scale-97 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=destructive]/toast:border-danger group-data-[variant=destructive]/toast:bg-danger motion-reduce:transition-[background-color] motion-reduce:active:scale-100\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction ToastClose({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Close>) {\n  return (\n    <ToastPrimitive.Close\n      data-slot=\"toast-close\"\n      aria-label=\"Close\"\n      className={cn(\n        \"absolute top-1/2 right-2 grid size-7 -translate-y-1/2 place-items-center rounded-sm text-fg-muted opacity-60 outline-none transition-[opacity,background-color] duration-150 ease-out hover:bg-wash-hover hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-0 focus-visible:outline-solid focus-visible:outline-focus-ring motion-reduce:transition-none [&_svg]:size-3.5\",\n        className,\n      )}\n      {...props}\n    >\n      <X strokeWidth={1.5} />\n    </ToastPrimitive.Close>\n  );\n}\n\nfunction ToastTitle({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Title>) {\n  return <ToastPrimitive.Title data-slot=\"toast-title\" className={cn(\"text-body-sm leading-snug font-medium text-fg\", className)} {...props} />;\n}\n\nfunction ToastDescription({ className, ...props }: React.ComponentProps<typeof ToastPrimitive.Description>) {\n  return <ToastPrimitive.Description data-slot=\"toast-description\" className={cn(\"text-caption leading-snug text-fg-muted\", className)} {...props} />;\n}\n\ntype ToastProps = React.ComponentProps<typeof Toast>;\ntype ToastActionElement = React.ReactElement<React.ComponentProps<typeof ToastAction>>;\n\n// The toast queue: a tiny store any part of the app can push to with toast(), read by useToast() and <Toaster />.\nconst TOAST_LIMIT = 3;\nconst REMOVE_DELAY = 1000;\n\ntype ToasterToast = ToastProps & { id: string; title?: React.ReactNode; description?: React.ReactNode; action?: ToastActionElement };\ntype State = { toasts: ToasterToast[] };\n\nlet count = 0;\nconst nextId = () => String((count = (count + 1) % Number.MAX_SAFE_INTEGER));\nconst listeners: Array<(state: State) => void> = [];\nlet memory: State = { toasts: [] };\nconst timeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction setState(update: (state: State) => State) {\n  memory = update(memory);\n  listeners.forEach((l) => l(memory));\n}\n\nfunction scheduleRemove(id: string) {\n  if (timeouts.has(id)) return;\n  // ds-latency: removes an already dismissed toast from memory; dismissal and input stay immediate.\n  timeouts.set(id, setTimeout(() => {\n    timeouts.delete(id);\n    setState((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) }));\n  }, REMOVE_DELAY));\n}\n\nfunction dismiss(id?: string) {\n  setState((s) => ({ toasts: s.toasts.map((t) => (id === undefined || t.id === id ? { ...t, open: false } : t)) }));\n  memory.toasts.filter((t) => id === undefined || t.id === id).forEach((t) => scheduleRemove(t.id));\n}\n\nfunction toast(props: Omit<ToasterToast, \"id\">) {\n  const id = nextId();\n  const update = (next: Partial<ToasterToast>) => setState((s) => ({ toasts: s.toasts.map((t) => (t.id === id ? { ...t, ...next } : t)) }));\n  setState((s) => ({\n    toasts: [{ ...props, id, open: true, onOpenChange: (open: boolean) => { if (!open) dismiss(id); props.onOpenChange?.(open); } }, ...s.toasts].slice(0, TOAST_LIMIT),\n  }));\n  return { id, dismiss: () => dismiss(id), update };\n}\n\nfunction useToast() {\n  const [state, setLocal] = React.useState(memory);\n  React.useEffect(() => {\n    listeners.push(setLocal);\n    return () => {\n      const i = listeners.indexOf(setLocal);\n      if (i > -1) listeners.splice(i, 1);\n    };\n  }, []);\n  return { ...state, toast, dismiss };\n}\n\n/** Renders the queue. Mount it once, near the root. */\nfunction Toaster() {\n  const { toasts } = useToast();\n  return (\n    <ToastProvider swipeDirection=\"left\">\n      {toasts.map(({ id, title, description, action, ...props }) => (\n        <Toast key={id} {...props}>\n          <div className=\"grid min-w-0 gap-0.5\">\n            {title && <ToastTitle>{title}</ToastTitle>}\n            {description && <ToastDescription>{description}</ToastDescription>}\n          </div>\n          {action}\n          <ToastClose />\n        </Toast>\n      ))}\n      <ToastViewport />\n    </ToastProvider>\n  );\n}\n\nexport { Toast, ToastAction, ToastClose, ToastDescription, Toaster, ToastProvider, ToastTitle, ToastViewport, toast, useToast };\nexport type { ToastActionElement, ToastProps };\n"
    }
  ]
}
