{
  "schemaVersion": 1,
  "name": "dialog",
  "useFor": "Use for a short form or confirmation. Provide a title and description. Set name for the title bar and size for wider content. Connect form submission and validation to the application.",
  "constraints": [
    "Dialogs for long reading",
    "A dialog opened from another dialog",
    "Sliding in from an edge (use a sheet)"
  ],
  "documentation": "",
  "source": "Extension from opencommerce-agentcard-web src/app/globals.css (.win, .win-bar, .win-mark)",
  "exports": [
    "Dialog",
    "DialogBody",
    "DialogClose",
    "DialogContent",
    "DialogDescription",
    "DialogFooter",
    "DialogHeader",
    "DialogOverlay",
    "DialogPortal",
    "DialogTitle",
    "DialogTrigger",
    "WindowClose"
  ],
  "client": true,
  "docsUrl": "https://opencommerce-ds.vercel.app/components/dialog",
  "markdownUrl": "https://opencommerce-ds.vercel.app/r/dialog.md",
  "examples": [
    {
      "path": "examples/dialog.tsx",
      "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from \"@/components/ui/dialog\";\nimport { Field } from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\n\nfunction NewCard({ defaultOpen = false }: { defaultOpen?: boolean }) {\n  const [open, setOpen] = useState(defaultOpen);\n  const [created, setCreated] = useState(\"\");\n  const formId = useId();\n  return <div className=\"grid gap-3\">\n    <Dialog open={open} onOpenChange={setOpen}>\n      <DialogTrigger asChild><Button>New card</Button></DialogTrigger>\n      <DialogContent name=\"card.new\">\n        <DialogHeader>\n          <DialogTitle>Give an agent a card</DialogTitle>\n          <DialogDescription>Name the card and set the most it can spend at one checkout. You can change both later.</DialogDescription>\n        </DialogHeader>\n        <DialogBody>\n          <form id={formId} className=\"grid gap-4\" onSubmit={(event) => {\n            event.preventDefault();\n            const data = new FormData(event.currentTarget);\n            setCreated(`${String(data.get(\"name\")).trim()} created with a $${Number(data.get(\"limit\")).toFixed(2)} purchase limit.`);\n            setOpen(false);\n          }}>\n            <Field label=\"Card name\" required><Input name=\"name\" defaultValue=\"Travel agent\" pattern=\".*\\S.*\" /></Field>\n            <Field label=\"Per purchase limit\" required help=\"Amount in USD.\"><Input name=\"limit\" type=\"number\" min=\"0.01\" step=\"0.01\" defaultValue=\"250\" /></Field>\n          </form>\n        </DialogBody>\n        <DialogFooter>\n          <DialogClose asChild><Button variant=\"secondary\">Cancel</Button></DialogClose>\n          <Button type=\"submit\" form={formId}>Create card</Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n    <p role=\"status\" className=\"text-body-sm text-fg-muted empty:hidden\">{created}</p>\n  </div>;\n}\nexport function Site() { return <NewCard />; }\nexport function Open() { return <div className=\"h-130\"><NewCard defaultOpen /></div>; }\n",
      "exports": [
        "Site",
        "Open"
      ],
      "requires": [
        "dialog",
        "button",
        "field",
        "input"
      ],
      "packages": [],
      "previews": [
        {
          "name": "Site",
          "url": "https://opencommerce-ds.vercel.app/preview/dialog/Site"
        },
        {
          "name": "Open",
          "url": "https://opencommerce-ds.vercel.app/preview/dialog/Open"
        }
      ]
    }
  ],
  "type": "ui",
  "title": "Dialog",
  "description": "Modal dialog with a title bar, focus trap and close control.",
  "surface": "site",
  "kinds": [
    "window",
    "window-bar"
  ],
  "requires": [
    "theme",
    "window",
    "surface",
    "utils"
  ],
  "packages": [
    "@radix-ui/react-dialog",
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/ui/dialog.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { X } from \"lucide-react\";\n\nimport { WindowBar } from \"@/components/ui/window\";\nimport { usePortalContainer } from \"@/lib/surface\";\nimport { cn } from \"@/lib/utils\";\n\n// A dialog is one of the brand's windows: white, a 16 percent ink edge, 12px corners, the 36px mist title bar with\n// its arrow and a file-like name (`name`), and a close mark where the [*] sits. It floats centered over a 40 percent\n// ink scrim, popping in from scale 0.97 with a fade (200ms ease-out; a modal stays centered, so it scales from its own\n// middle). Reduced motion keeps the fade. Radix adds the focus trap, scroll lock and Escape.\nfunction Dialog(props: React.ComponentProps<typeof DialogPrimitive.Root>) {\n  return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger(props: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n  return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogClose(props: React.ComponentProps<typeof DialogPrimitive.Close>) {\n  return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogPortal(props: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n  const container = usePortalContainer();\n  return <DialogPrimitive.Portal data-slot=\"dialog-portal\" container={container} {...props} />;\n}\n\nfunction DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n  return <DialogPrimitive.Overlay data-slot=\"dialog-overlay\" className={cn(\"fixed inset-0 z-50 animate-fade-in motion-reduce:animate-none bg-scrim\", className)} {...props} />;\n}\n\n/** The close mark in a window bar, in the bar's own color. */\nfunction WindowClose({ className }: { className?: string }) {\n  return (\n    <DialogPrimitive.Close\n      aria-label=\"Close\"\n      className={cn(\n        \"-mr-1.5 grid size-7 shrink-0 place-items-center rounded-sm 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 [&_svg]:size-3.5\",\n        className,\n      )}\n    >\n      <X strokeWidth={1.5} />\n    </DialogPrimitive.Close>\n  );\n}\n\nconst WIDTHS = { md: \"max-w-lg\", lg: \"max-w-3xl\", xl: \"max-w-5xl\", \"2xl\": \"max-w-6xl\" } as const;\n\nfunction DialogContent({\n  className,\n  children,\n  size = \"md\",\n  name = \"dialog\",\n  tone,\n  showCloseButton = true,\n  ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n  size?: keyof typeof WIDTHS;\n  /** The title bar's label, file-like: `card.new`, `agent.pause`. */\n  name?: React.ReactNode;\n  /** The bar's tone: mist (the default); see Window. */\n  tone?: React.ComponentProps<typeof WindowBar>[\"tone\"];\n  showCloseButton?: boolean;\n}) {\n  return (\n    <DialogPortal>\n      <DialogOverlay />\n      <DialogPrimitive.Content\n        data-slot=\"dialog-content\"\n        className={cn(\n          \"fixed top-1/2 left-1/2 z-50 flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] -translate-1/2 animate-pop-in motion-reduce:animate-none flex-col overflow-hidden rounded-panel border border-line-window bg-surface text-fg shadow-floating outline-none [animation-duration:var(--ds-duration-base)]\",\n          WIDTHS[size],\n          className,\n        )}\n        {...props}\n      >\n        <WindowBar name={name} tone={tone} actions={showCloseButton ? <WindowClose /> : undefined} />\n        <div className=\"relative min-h-0 flex-1 overflow-y-auto\">{children}</div>\n      </DialogPrimitive.Content>\n    </DialogPortal>\n  );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return <div data-slot=\"dialog-header\" className={cn(\"flex flex-col gap-2 px-6 pt-6\", className)} {...props} />;\n}\n\nfunction DialogBody({ className, ...props }: React.ComponentProps<\"div\">) {\n  return <div data-slot=\"dialog-body\" className={cn(\"px-6 pt-5 pb-6 text-body text-fg\", className)} {...props} />;\n}\n\nfunction DialogFooter({ className, divider = true, ...props }: React.ComponentProps<\"div\"> & { divider?: boolean }) {\n  return <div data-slot=\"dialog-footer\" className={cn(\"flex flex-wrap items-center justify-end gap-3 px-6\", divider ? \"border-t border-line py-4\" : \"pb-6\", className)} {...props} />;\n}\n\n// 24px display at 500, tracked tight, like a card's title.\nfunction DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n  return <DialogPrimitive.Title data-slot=\"dialog-title\" className={cn(\"font-display text-h3 leading-display font-medium tracking-tight text-fg\", className)} {...props} />;\n}\n\nfunction DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n  return <DialogPrimitive.Description data-slot=\"dialog-description\" className={cn(\"text-body-sm leading-relaxed text-fg-muted\", className)} {...props} />;\n}\n\nexport { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, WindowClose };\n"
    }
  ]
}
