{
  "schemaVersion": 1,
  "name": "sonner",
  "useFor": "Mount one Toaster near the application root. Show a toast after an action succeeds or fails. Connect any toast action to its intended behavior.",
  "constraints": [
    "Toasts for errors that need an answer (use a dialog or a banner)",
    "More than one action",
    "Dark toasts",
    "Long sentences in a toast"
  ],
  "documentation": "",
  "source": "Extension from opencommerce-agentcard-web src/app/globals.css (.feat-order, .feat-node)",
  "exports": [
    "Toaster"
  ],
  "client": true,
  "docsUrl": "https://opencommerce-ds.vercel.app/components/sonner",
  "markdownUrl": "https://opencommerce-ds.vercel.app/r/sonner.md",
  "examples": [
    {
      "path": "examples/sonner.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { useCopy } from \"@/components/ui/copy-button\";\nimport { Toaster } from \"@/components/ui/sonner\";\n\nexport function Site() {\n  const { copy } = useCopy();\n  return <div className=\"relative h-40\">\n    <Button variant=\"secondary\" onClick={async () => {\n      const copied = await copy(\"ac_demo_7Hq2\");\n      if (copied) toast.success(\"Key copied\", { id: \"key-copied\", toasterId: \"toast-example\", description: \"ac_demo_7Hq2\" });\n      else toast.error(\"Could not copy the key\", { id: \"key-copied\", toasterId: \"toast-example\", description: \"Check clipboard access and try again.\" });\n    }}>Copy key</Button>\n    <Toaster id=\"toast-example\" style={{ position: \"absolute\" }} offset={{ left: 0, bottom: 0 }} mobileOffset={{ left: 0, bottom: 0 }} />\n  </div>;\n}\nexport function Action() {\n  const [viewing, setViewing] = useState(false);\n  return <div className=\"relative min-h-40\">\n    <Button variant=\"secondary\" onClick={() => {\n      setViewing(false);\n      toast.success(\"Card created\", { id: \"card-created\", toasterId: \"toast-action\", description: \"Travel agent\", duration: Infinity,\n        action: { label: \"View card\", onClick: () => setViewing(true) } });\n    }}>Create card</Button>\n    {viewing && <p className=\"mt-3 text-body-sm\" role=\"status\">Travel agent · Active · $250 per purchase</p>}\n    <Toaster id=\"toast-action\" style={{ position: \"absolute\" }} offset={{ left: 0, bottom: 0 }} mobileOffset={{ left: 0, bottom: 0 }} />\n  </div>;\n}\n",
      "exports": [
        "Site",
        "Action"
      ],
      "requires": [
        "sonner",
        "button",
        "copy-button"
      ],
      "packages": [
        "sonner"
      ],
      "previews": [
        {
          "name": "Site",
          "url": "https://opencommerce-ds.vercel.app/preview/sonner/Site"
        },
        {
          "name": "Action",
          "url": "https://opencommerce-ds.vercel.app/preview/sonner/Action"
        }
      ]
    }
  ],
  "type": "ui",
  "title": "Toast",
  "description": "Toast notifications with optional actions.",
  "surface": "site",
  "kinds": [],
  "requires": [
    "theme",
    "utils"
  ],
  "packages": [
    "sonner"
  ],
  "files": [
    {
      "path": "components/ui/sonner.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\";\n\nimport { cn } from \"@/lib/utils\";\n\n// The brand's toast: a white card at the bottom left, one 40px line high, a 9 percent ink edge, 8px corners and a soft\n// drop; a 24px blue square with a white tick at its left (the order card's done step), then the title (14px Inter at\n// 500) and its line (12px, 64 percent ink) side by side. An action is a small blue key at the right, cancel a small\n// white one; both shrink to 0.97 when pressed. Sonner places, stacks and swipes it (its own\n// enter and exit motion); this only draws it.\nconst KEY = \"grid size-6 shrink-0 place-items-center rounded-sm border text-on-primary [&_svg]:size-3 [&_svg]:fill-none [&_svg]:stroke-current [&_svg]:[stroke-linecap:round] [&_svg]:[stroke-linejoin:round] [&_svg]:[stroke-width:2]\";\n\nfunction Mark({ d }: { d: string }) {\n  return (\n    <svg viewBox=\"0 0 16 16\" aria-hidden>\n      <path d={d} />\n    </svg>\n  );\n}\n\nconst TICK = \"M3.5 8.5 6.5 11.5 12.5 4.5\";\n\nfunction Toaster({ toastOptions, ...props }: ToasterProps) {\n  return (\n    <Sonner\n      className=\"toaster group\"\n      position=\"bottom-left\"\n      offset={{ left: 30, bottom: 20 }}\n      mobileOffset={{ left: 18, bottom: 20 }}\n      visibleToasts={3}\n      icons={{\n        success: <Mark d={TICK} />,\n        info: <Mark d=\"M8 7v5M8 4.5v.01\" />,\n        warning: <Mark d=\"M8 4v5M8 11.5v.01\" />,\n        error: <Mark d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" />,\n      }}\n      toastOptions={{\n        unstyled: true,\n        ...toastOptions,\n        classNames: {\n          toast:\n            \"flex h-10 w-max max-w-[calc(100vw-2.25rem)] items-center gap-2.5 rounded-control border border-line bg-surface pr-1.5 pl-1.75 font-sans text-fg shadow-floating [&:not(:has([data-button]))]:pr-3.5\",\n          icon: cn(KEY, \"m-0 border-line-brand-edge bg-primary\"),\n          content: \"flex min-w-0 items-baseline gap-2\",\n          title: \"font-sans text-body-sm leading-snug font-medium whitespace-nowrap\",\n          description: \"max-w-55 truncate font-sans text-caption leading-snug text-fg-muted\",\n          actionButton:\n            \"ml-1.5 h-7 shrink-0 cursor-pointer 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 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring active:scale-97 motion-reduce:transition-[background-color] motion-reduce:active:scale-100\",\n          cancelButton:\n            \"ml-1.5 h-7 shrink-0 cursor-pointer rounded-sm border border-hairline bg-surface px-2.5 font-sans text-caption font-medium text-fg outline-none transition-[background-color,scale] duration-160 ease-out hover:bg-subtle focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring active:scale-97 motion-reduce:transition-[background-color] motion-reduce:active:scale-100\",\n          error: \"[&_[data-icon]]:border-danger [&_[data-icon]]:bg-danger\",\n          warning: \"[&_[data-icon]]:border-warning [&_[data-icon]]:bg-warning\",\n          ...toastOptions?.classNames,\n        },\n      }}\n      {...props}\n    />\n  );\n}\n\nexport { Toaster };\n"
    }
  ]
}
