{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dialog",
  "title": "Dialog",
  "description": "The lights go down and a panel rises onto the desk, screwed or stitched at its corners. Content has no padding of its own, so it hosts forms and command palettes alike; AlertDialog asks before something can't be undone.",
  "dependencies": [
    "@base-ui/react",
    "cn"
  ],
  "registryDependencies": [
    "https://bevel-ui.vercel.app/r/bevel.json"
  ],
  "files": [
    {
      "path": "registry/bevel/ui/dialog.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { AlertDialog as AlertDialogPrimitive } from \"@base-ui/react/alert-dialog\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\nimport { cn } from \"cn\"\n\ntype Fasteners = \"screws\" | \"stitch\" | \"none\"\n\n/* The room's lights go down slowly, and come back up quicker. */\nconst dim = cn(\n  \"dialog-dim fixed inset-0 z-50\",\n  \"transition-opacity duration-(--bevel-duration-ambient) ease-(--bevel-ease-in-out) motion-reduce:transition-none\",\n  \"data-starting-style:opacity-0 data-ending-style:opacity-0 data-ending-style:duration-(--bevel-duration-move) data-ending-style:ease-(--bevel-ease-out)\"\n)\n\nconst viewport = \"fixed inset-0 z-50 flex items-center justify-center p-4 data-[align=top]:items-start data-[align=top]:pt-(--dialog-top)\"\n\n/* The panel rises onto the desk and settles; it leaves quickly. */\nconst panel = cn(\n  \"dialog-panel relative flex max-h-full w-full flex-col overflow-hidden rounded-(--bevel-radius-lg) text-sm outline-none\",\n  \"transition-[translate,opacity] duration-(--bevel-duration-move) ease-(--bevel-ease-spring) motion-reduce:transition-none\",\n  \"data-starting-style:translate-y-(--dialog-rise) data-starting-style:opacity-0\",\n  \"data-ending-style:translate-y-(--dialog-rise) data-ending-style:opacity-0 data-ending-style:duration-(--bevel-duration-small) data-ending-style:ease-(--bevel-ease-out)\",\n  \"forced-colors:border forced-colors:border-[CanvasText]\"\n)\n\nconst key = cn(\n  \"bevel-raised inline-flex h-8 items-center justify-center gap-1.5 rounded-(--bevel-radius-sm) px-3 text-sm font-medium whitespace-nowrap text-(--dialog-key-ink) outline-none select-none\",\n  \"transition-[translate] duration-(--bevel-duration-press) ease-(--bevel-ease-out) motion-reduce:transition-none\",\n  \"active:translate-y-px active:bevel-pressed focus-visible:ring-2 focus-visible:ring-(--bevel-pen-blue)/60 focus-visible:ring-offset-1\",\n  \"data-disabled:pointer-events-none data-disabled:opacity-50\",\n  \"forced-colors:border forced-colors:border-[ButtonText]\"\n)\n\n/** Screws at the four corners, each at its own angle, or a stitched edge. Decorative. */\nfunction DialogFasteners({ fasteners }: { fasteners: Fasteners }) {\n  if (fasteners === \"none\") return null\n  if (fasteners === \"stitch\")\n    return (\n      <span\n        aria-hidden\n        data-slot=\"dialog-stitch\"\n        className=\"pointer-events-none absolute inset-(--bevel-stitch-inset) rounded-[calc(var(--bevel-radius-lg)-var(--bevel-stitch-inset))] border-(length:--bevel-stitch-width) border-dashed border-(--dialog-stitch)\"\n      />\n    )\n  return (\n    <span aria-hidden data-slot=\"dialog-screws\" className=\"pointer-events-none absolute inset-(--dialog-screw-inset)\">\n      <span className=\"dialog-screw absolute top-0 left-0\" />\n      <span className=\"dialog-screw absolute top-0 right-0\" />\n      <span className=\"dialog-screw absolute bottom-0 left-0\" />\n      <span className=\"dialog-screw absolute right-0 bottom-0\" />\n    </span>\n  )\n}\n\nfunction CornerClose() {\n  return (\n    <DialogPrimitive.Close\n      data-slot=\"dialog-corner-close\"\n      aria-label=\"Close\"\n      className=\"absolute top-4 right-4 z-10 inline-flex size-7 items-center justify-center rounded-(--bevel-radius-sm) text-(--dialog-panel-muted) outline-none hover:text-(--dialog-panel-foreground) focus-visible:ring-2 focus-visible:ring-(--bevel-pen-blue)/60\"\n    >\n      <svg aria-hidden viewBox=\"0 0 16 16\" className=\"size-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\">\n        <path d=\"M4 4l8 8M12 4l-8 8\" />\n      </svg>\n    </DialogPrimitive.Close>\n  )\n}\n\n/* Dialog ------------------------------------------------------------------ */\n\n/** A trigger and the panel it brings up. Escape, the backdrop and Close all put it away, and focus returns to the trigger. */\nfunction Dialog(props: DialogPrimitive.Root.Props) {\n  return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\n/** Opens the dialog. Renders a button; pass `render` to use your own. */\nfunction DialogTrigger(props: DialogPrimitive.Trigger.Props) {\n  return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\ntype DialogContentProps = DialogPrimitive.Popup.Props & {\n  /** \"top\" sits the panel near the top of the screen, for a command palette. */\n  align?: \"center\" | \"top\"\n  /** What holds the panel down at its corners. */\n  fasteners?: Fasteners\n  /** A × in the top corner. Turn off when the content has its own way out. */\n  showCloseButton?: boolean\n}\n\n/**\n * The lights go down and the panel rises onto the desk. No padding of its\n * own: compose DialogHeader, DialogBody and DialogFooter, or put a command\n * palette straight in.\n */\nfunction DialogContent({\n  className,\n  children,\n  align = \"center\",\n  fasteners = \"screws\",\n  showCloseButton = true,\n  ...props\n}: DialogContentProps) {\n  return (\n    <DialogPrimitive.Portal>\n      <DialogPrimitive.Backdrop data-slot=\"dialog-backdrop\" className={dim} />\n      <DialogPrimitive.Viewport data-slot=\"dialog-viewport\" data-align={align} className={viewport}>\n        <DialogPrimitive.Popup\n          data-slot=\"dialog-content\"\n          data-fasteners={fasteners}\n          className={cn(panel, \"max-w-(--dialog-width)\", className)}\n          {...props}\n        >\n          <DialogFasteners fasteners={fasteners} />\n          {children}\n          {showCloseButton && <CornerClose />}\n        </DialogPrimitive.Popup>\n      </DialogPrimitive.Viewport>\n    </DialogPrimitive.Portal>\n  )\n}\n\n/** Title and description. Leaves room for the corner ×. */\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"dialog-header\"\n      className={cn(\"flex shrink-0 flex-col gap-1.5 px-6 pt-6 pr-12\", className)}\n      {...props}\n    />\n  )\n}\n\n/** Names the dialog for screen readers. */\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n  return (\n    <DialogPrimitive.Title\n      data-slot=\"dialog-title\"\n      className={cn(\"text-base leading-tight font-semibold\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction DialogDescription({ className, ...props }: DialogPrimitive.Description.Props) {\n  return (\n    <DialogPrimitive.Description\n      data-slot=\"dialog-description\"\n      className={cn(\"text-sm text-(--dialog-panel-muted)\", className)}\n      {...props}\n    />\n  )\n}\n\n/** The content between header and footer. Scrolls when the panel runs out of room. */\nfunction DialogBody({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"dialog-body\"\n      // Focusable, so a body that scrolls can be scrolled from the keyboard.\n      tabIndex={0}\n      className={cn(\n        \"min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\n/** A ledge along the bottom, behind an engraved rule, holding the keys. */\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"dialog-footer\"\n      className={cn(\n        \"mt-4 flex shrink-0 flex-col-reverse gap-2 border-t border-t-(--dialog-rule-shade) bg-(--dialog-ledge) px-6 py-4 shadow-[inset_0_1px_0_var(--dialog-rule-light)] sm:flex-row sm:justify-end\",\n        \"[[data-slot=dialog-body]+&]:mt-0\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype DialogCloseProps = DialogPrimitive.Close.Props & {\n  /** \"destructive\" makes it the red key. */\n  tone?: \"default\" | \"destructive\"\n}\n\n/** A key that closes the dialog. Use it for Cancel, Done, or an action that ends with closing. */\nfunction DialogClose({ className, tone = \"default\", ...props }: DialogCloseProps) {\n  return <DialogPrimitive.Close data-slot=\"dialog-close\" data-tone={tone} className={cn(key, className)} {...props} />\n}\n\n/* Alert dialog ------------------------------------------------------------ */\n\n/** A dialog that needs an answer: it doesn't close on an outside click. For destructive confirmation. */\nfunction AlertDialog(props: AlertDialogPrimitive.Root.Props) {\n  return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger(props: AlertDialogPrimitive.Trigger.Props) {\n  return <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n}\n\ntype AlertDialogContentProps = AlertDialogPrimitive.Popup.Props & {\n  fasteners?: Fasteners\n}\n\n/** The same panel, narrower, with no corner ×: answer it or press Escape. */\nfunction AlertDialogContent({ className, children, fasteners = \"screws\", ...props }: AlertDialogContentProps) {\n  return (\n    <AlertDialogPrimitive.Portal>\n      <AlertDialogPrimitive.Backdrop data-slot=\"alert-dialog-backdrop\" className={dim} />\n      <AlertDialogPrimitive.Viewport data-slot=\"alert-dialog-viewport\" className={viewport}>\n        <AlertDialogPrimitive.Popup\n          data-slot=\"alert-dialog-content\"\n          data-fasteners={fasteners}\n          className={cn(panel, \"max-w-(--dialog-alert-width)\", className)}\n          {...props}\n        >\n          <DialogFasteners fasteners={fasteners} />\n          {children}\n        </AlertDialogPrimitive.Popup>\n      </AlertDialogPrimitive.Viewport>\n    </AlertDialogPrimitive.Portal>\n  )\n}\n\nfunction AlertDialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return <DialogHeader data-slot=\"alert-dialog-header\" className={cn(\"pr-6\", className)} {...props} />\n}\n\nfunction AlertDialogTitle({ className, ...props }: AlertDialogPrimitive.Title.Props) {\n  return (\n    <AlertDialogPrimitive.Title\n      data-slot=\"alert-dialog-title\"\n      className={cn(\"text-base leading-tight font-semibold\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogDescription({ className, ...props }: AlertDialogPrimitive.Description.Props) {\n  return (\n    <AlertDialogPrimitive.Description\n      data-slot=\"alert-dialog-description\"\n      className={cn(\"text-sm text-(--dialog-panel-muted)\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction AlertDialogFooter(props: React.ComponentProps<\"div\">) {\n  return <DialogFooter data-slot=\"alert-dialog-footer\" {...props} />\n}\n\n/** The safe answer. Put it first: it takes focus when the dialog opens. */\nfunction AlertDialogCancel({ className, children = \"Cancel\", ...props }: AlertDialogPrimitive.Close.Props) {\n  return (\n    <AlertDialogPrimitive.Close data-slot=\"alert-dialog-cancel\" className={cn(key, className)} {...props}>\n      {children}\n    </AlertDialogPrimitive.Close>\n  )\n}\n\ntype AlertDialogActionProps = AlertDialogPrimitive.Close.Props & {\n  /** Red by default: alert dialogs are for things that can't be undone. */\n  tone?: \"default\" | \"destructive\"\n}\n\n/** Does the thing and closes. Runs onClick first, so do the work there. */\nfunction AlertDialogAction({ className, tone = \"destructive\", ...props }: AlertDialogActionProps) {\n  return (\n    <AlertDialogPrimitive.Close\n      data-slot=\"alert-dialog-action\"\n      data-tone={tone}\n      className={cn(key, className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Dialog,\n  DialogTrigger,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogDescription,\n  DialogBody,\n  DialogFooter,\n  DialogClose,\n  AlertDialog,\n  AlertDialogTrigger,\n  AlertDialogContent,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogCancel,\n  AlertDialogAction,\n}\nexport type { DialogContentProps, DialogCloseProps, AlertDialogContentProps, AlertDialogActionProps }\n",
      "type": "registry:ui"
    }
  ],
  "css": {
    ":root": {
      "--dialog-panel": "oklch(0.985 0.005 85)",
      "--dialog-panel-foreground": "oklch(0.26 0.015 260)",
      "--dialog-panel-muted": "oklch(0.5 0.015 260)",
      "--dialog-ledge": "oklch(0.955 0.007 85)",
      "--dialog-rim": "oklch(0 0 0 / 0.12)",
      "--dialog-rule-shade": "oklch(0 0 0 / 0.1)",
      "--dialog-rule-light": "oklch(1 0 0 / 0.8)",
      "--dialog-dim": "oklch(0.14 0.01 260 / 0.42)",
      "--dialog-dim-brightness": "0.8",
      "--dialog-screw": "oklch(0.8 0.01 250)",
      "--dialog-screw-slot": "oklch(0.35 0.01 250 / 0.7)",
      "--dialog-stitch": "oklch(0.55 0.02 260 / 0.35)",
      "--dialog-key": "oklch(0.97 0.004 85)",
      "--dialog-key-edge": "oklch(0.76 0.008 250)",
      "--dialog-key-foreground": "oklch(0.26 0.015 260)",
      "--dialog-danger": "oklch(0.55 0.2 27)",
      "--dialog-danger-edge": "oklch(0.38 0.15 27)",
      "--dialog-danger-foreground": "oklch(0.99 0.005 90)",
      "--dialog-depth": "inset 0 1px 0 var(--bevel-highlight-strong), 0 0 0 1px var(--dialog-rim), 0 2px 4px var(--bevel-cast), 0 30px 60px -20px var(--bevel-cast)",
      "--dialog-width": "32rem",
      "--dialog-alert-width": "26rem",
      "--dialog-top": "12vh",
      "--dialog-rise": "1rem",
      "--dialog-screw-size": "0.4375rem",
      "--dialog-screw-inset": "0.5rem"
    },
    ".dark": {
      "--dialog-panel": "oklch(0.29 0.008 260)",
      "--dialog-panel-foreground": "oklch(0.95 0.005 90)",
      "--dialog-panel-muted": "oklch(0.72 0.01 260)",
      "--dialog-ledge": "oklch(0.255 0.008 260)",
      "--dialog-rim": "oklch(1 0 0 / 0.08)",
      "--dialog-rule-shade": "oklch(0 0 0 / 0.45)",
      "--dialog-rule-light": "oklch(1 0 0 / 0.06)",
      "--dialog-dim": "oklch(0.05 0.01 260 / 0.6)",
      "--dialog-dim-brightness": "0.6",
      "--dialog-screw": "oklch(0.55 0.01 250)",
      "--dialog-screw-slot": "oklch(0.15 0.01 250 / 0.8)",
      "--dialog-stitch": "oklch(0.85 0.02 260 / 0.25)",
      "--dialog-key": "oklch(0.38 0.008 260)",
      "--dialog-key-edge": "oklch(0.2 0.008 260)",
      "--dialog-key-foreground": "oklch(0.95 0.005 90)",
      "--dialog-danger": "oklch(0.55 0.19 27)",
      "--dialog-danger-edge": "oklch(0.32 0.13 27)"
    },
    "@utility dialog-panel": {
      "background-color": "var(--dialog-panel)",
      "background-image": "linear-gradient(to bottom, var(--bevel-highlight), transparent 20%)",
      "box-shadow": "var(--dialog-depth)",
      "color": "var(--dialog-panel-foreground)"
    },
    "@utility dialog-dim": {
      "background-color": "var(--dialog-dim)",
      "backdrop-filter": "brightness(var(--dialog-dim-brightness))"
    },
    "@utility dialog-screw": {
      "width": "var(--dialog-screw-size)",
      "height": "var(--dialog-screw-size)",
      "border-radius": "9999px",
      "background-color": "var(--dialog-screw)",
      "background-image": "linear-gradient(var(--dialog-screw-angle, 30deg), transparent 42%, var(--dialog-screw-slot) 42% 58%, transparent 58%), radial-gradient(circle at 35% 30%, var(--bevel-highlight-strong), transparent 60%)",
      "box-shadow": "inset 0 -1px 1px var(--bevel-shade), 0 1px 0 var(--bevel-highlight-strong)"
    },
    "[data-slot=\"dialog-screws\"] > :nth-child(1)": {
      "--dialog-screw-angle": "20deg"
    },
    "[data-slot=\"dialog-screws\"] > :nth-child(2)": {
      "--dialog-screw-angle": "75deg"
    },
    "[data-slot=\"dialog-screws\"] > :nth-child(3)": {
      "--dialog-screw-angle": "130deg"
    },
    "[data-slot=\"dialog-screws\"] > :nth-child(4)": {
      "--dialog-screw-angle": "160deg"
    },
    "[data-slot=\"dialog-close\"], [data-slot=\"alert-dialog-cancel\"], [data-slot=\"alert-dialog-action\"]": {
      "--bevel-material": "var(--dialog-key)",
      "--bevel-material-edge": "var(--dialog-key-edge)",
      "--dialog-key-ink": "var(--dialog-key-foreground)"
    },
    "[data-tone=\"destructive\"]:is([data-slot=\"dialog-close\"], [data-slot=\"alert-dialog-action\"])": {
      "--bevel-material": "var(--dialog-danger)",
      "--bevel-material-edge": "var(--dialog-danger-edge)",
      "--dialog-key-ink": "var(--dialog-danger-foreground)"
    }
  },
  "categories": [
    "essentials"
  ],
  "type": "registry:ui"
}