{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sheet",
  "type": "registry:ui",
  "title": "Sheet",
  "description": "A folder that slides in from the edge, with a tab.",
  "categories": [
    "core"
  ],
  "files": [
    {
      "path": "ui/sheet.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Dialog as SheetPrimitive } from \"radix-ui\";\n\n// Popups render in a layer on <body> that copies the paper type of the nearest [data-paper]\n// element (and follows it if it changes). That keeps their theme without trapping them inside the\n// container's stacking context, so sticky headers can't cover them.\nfunction usePaperContainer() {\n  const anchor = React.useRef<HTMLSpanElement>(null);\n  const [container, setContainer] = React.useState<HTMLElement | undefined>();\n  React.useEffect(() => {\n    const source = anchor.current?.closest<HTMLElement>(\"[data-paper]\");\n    if (!source || source === document.documentElement) return;\n    const layer = document.createElement(\"div\");\n    layer.setAttribute(\"data-paper-layer\", \"\");\n    const sync = () => layer.setAttribute(\"data-paper\", source.getAttribute(\"data-paper\") ?? \"\");\n    sync();\n    document.body.appendChild(layer);\n    const observer = new MutationObserver(sync);\n    observer.observe(source, { attributes: true, attributeFilter: [\"data-paper\"] });\n    setContainer(layer);\n    return () => {\n      observer.disconnect();\n      layer.remove();\n    };\n  }, []);\n  return [anchor, container] as const;\n}\n\n/** A folder that slides in from the edge of the desk. */\nexport const Sheet = SheetPrimitive.Root;\nexport const SheetTrigger = SheetPrimitive.Trigger;\nexport const SheetClose = SheetPrimitive.Close;\n\nconst sides = {\n  right:\n    \"inset-y-0 right-0 h-full w-[88%] max-w-md border-l data-[state=open]:animate-[paper-slide-in-right_.35s_cubic-bezier(.2,.9,.3,1)_both] data-[state=closed]:animate-[paper-slide-out-right_.25s_ease-in_both]\",\n  left: \"inset-y-0 left-0 h-full w-[88%] max-w-md border-r data-[state=open]:animate-[paper-slide-in-left_.35s_cubic-bezier(.2,.9,.3,1)_both] data-[state=closed]:animate-[paper-slide-out-left_.25s_ease-in_both]\",\n  bottom:\n    \"inset-x-0 bottom-0 max-h-[85vh] border-t data-[state=open]:animate-[paper-slide-in-bottom_.35s_cubic-bezier(.2,.9,.3,1)_both] data-[state=closed]:animate-[paper-slide-out-bottom_.25s_ease-in_both]\",\n} as const;\n\n// the folder tab that sticks out of the sheet\nconst tabs = {\n  right: \"left-0 top-10 -translate-x-full rounded-l-[6px] border-r-0 px-1.5 py-4 [writing-mode:vertical-rl] rotate-180\",\n  left: \"right-0 top-10 translate-x-full rounded-r-[6px] border-l-0 px-1.5 py-4 [writing-mode:vertical-rl]\",\n  bottom: \"left-8 top-0 -translate-y-full rounded-t-[6px] border-b-0 px-4 py-1.5\",\n} as const;\n\nexport function SheetContent({\n  className = \"\",\n  side = \"right\",\n  tab,\n  children,\n  ...props\n}: React.ComponentProps<typeof SheetPrimitive.Content> & { side?: keyof typeof sides; tab?: React.ReactNode }) {\n  const [anchor, container] = usePaperContainer();\n  return (\n    <>\n      <span ref={anchor} hidden />\n      <SheetPrimitive.Portal container={container}>\n        <SheetPrimitive.Overlay\n          data-paper-motion\n          className=\"fixed inset-0 z-50 bg-[rgb(28_22_14/.4)] data-[state=closed]:animate-[paper-fade-out_.25s_ease_both] data-[state=open]:animate-[paper-fade-in_.25s_ease_both]\"\n        />\n        <SheetPrimitive.Content\n          data-paper-motion\n          className={`fixed z-50 flex flex-col gap-4 border-(--edge) bg-(--paper-raised) p-7 text-(--ink) shadow-[0_0_50px_-10px_rgb(0_0_0/.5)] outline-none ${sides[side]} ${className}`}\n          {...props}\n        >\n          {tab && (\n            <span\n              aria-hidden\n              className={`absolute border border-(--edge) bg-(--paper-raised) text-[10px] font-bold uppercase tracking-[0.2em] text-(--ink-muted) ${tabs[side]}`}\n              style={{ fontFamily: \"var(--font-type, 'Courier New', monospace)\" }}\n            >\n              {tab}\n            </span>\n          )}\n          <div className=\"paper absolute inset-0 -z-10 bg-(--paper-raised)\" aria-hidden />\n          {children}\n          <SheetPrimitive.Close\n            className=\"absolute right-4 top-4 cursor-pointer rounded-[3px] px-1.5 text-[18px] leading-none text-(--ink-muted) outline-none hover:text-(--ink) focus-visible:ring-2 focus-visible:ring-(--pen)\"\n            style={{ fontFamily: \"var(--font-type, 'Courier New', monospace)\" }}\n            aria-label=\"Close\"\n          >\n            ×\n          </SheetPrimitive.Close>\n        </SheetPrimitive.Content>\n      </SheetPrimitive.Portal>\n    </>\n  );\n}\n\nexport function SheetHeader({ className = \"\", ...props }: React.HTMLAttributes<HTMLDivElement>) {\n  return <div className={`flex flex-col gap-1.5 pr-8 ${className}`} {...props} />;\n}\n\nexport function SheetFooter({ className = \"\", ...props }: React.HTMLAttributes<HTMLDivElement>) {\n  return <div className={`mt-auto flex flex-col-reverse gap-3 sm:flex-row sm:justify-end ${className}`} {...props} />;\n}\n\nexport function SheetTitle({ className = \"\", style, ...props }: React.ComponentProps<typeof SheetPrimitive.Title>) {\n  return (\n    <SheetPrimitive.Title\n      className={`text-[24px] font-semibold leading-tight tracking-tight ${className}`}\n      style={{ fontFamily: \"var(--font-display, Georgia, serif)\", ...style }}\n      {...props}\n    />\n  );\n}\n\nexport function SheetDescription({ className = \"\", ...props }: React.ComponentProps<typeof SheetPrimitive.Description>) {\n  return <SheetPrimitive.Description className={`text-[14px] leading-relaxed text-(--ink-muted) ${className}`} {...props} />;\n}\n"
    }
  ],
  "dependencies": [
    "radix-ui"
  ]
}