{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sheet",
  "title": "Sheet",
  "author": "Tori Bryan",
  "description": "A panel that slides in from an edge for a focused task.",
  "dependencies": [
    "@base-ui/react",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://fibo.toribryan.com/r/button.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/sheet.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as SheetPrimitive } from \"@base-ui/react/drawer\"\nimport { XIcon } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\n\ntype SheetSide = \"top\" | \"right\" | \"bottom\" | \"left\"\n\nconst SWIPE_DIRECTION = {\n  top: \"up\",\n  right: \"right\",\n  bottom: \"down\",\n  left: \"left\",\n} as const\n\n/*\n * Base UI sets the swipe direction on the root, so the side lives here\n * rather than on the content as it does in shadcn's Sheet.\n */\nfunction Sheet({\n  side = \"right\",\n  ...props\n}: Omit<SheetPrimitive.Root.Props, \"swipeDirection\"> & {\n  /** The edge it slides in from, and the way it's swiped away. */\n  side?: SheetSide\n}) {\n  return (\n    <SheetPrimitive.Root swipeDirection={SWIPE_DIRECTION[side]} {...props} />\n  )\n}\n\nfunction SheetTrigger(props: SheetPrimitive.Trigger.Props) {\n  return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose(props: SheetPrimitive.Close.Props) {\n  return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetContent({\n  className,\n  children,\n  showCloseButton = true,\n  keepMounted = false,\n  container,\n  ...props\n}: SheetPrimitive.Popup.Props & {\n  /** Shows a close button in the top corner. */\n  showCloseButton?: boolean\n  /** Keeps the content in the page while closed, so its controls keep their state. */\n  keepMounted?: boolean\n  /** The element the sheet portals into; the body by default. */\n  container?: SheetPrimitive.Portal.Props[\"container\"]\n}) {\n  return (\n    <SheetPrimitive.Portal keepMounted={keepMounted} container={container}>\n      <SheetPrimitive.Backdrop\n        data-slot=\"sheet-overlay\"\n        className=\"fixed inset-0 z-50 bg-backdrop opacity-[calc(1-var(--drawer-swipe-progress,0))] transition-opacity duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] data-ending-style:opacity-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*400ms)] data-starting-style:opacity-0 data-swiping:duration-0 motion-reduce:transition-none\"\n      />\n      <SheetPrimitive.Viewport className=\"fixed inset-0 z-50 overflow-hidden\">\n        <SheetPrimitive.Popup\n          data-slot=\"sheet-content\"\n          className={cn(\n            \"fixed z-50 flex flex-col gap-4 bg-background text-foreground shadow-lg transition-transform duration-[450ms] ease-[cubic-bezier(0.32,0.72,0,1)] outline-none data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*400ms)] data-swiping:select-none motion-reduce:transition-none\",\n            \"data-[swipe-direction=down]:inset-x-0 data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:max-h-[85dvh] data-[swipe-direction=down]:[transform:translateY(var(--drawer-swipe-movement-y,0px))] data-[swipe-direction=down]:rounded-t-xl data-[swipe-direction=down]:border-t data-[swipe-direction=down]:border-border data-[swipe-direction=down]:pb-[env(safe-area-inset-bottom)] data-[swipe-direction=down]:data-ending-style:[transform:translateY(100%)] data-[swipe-direction=down]:data-starting-style:[transform:translateY(100%)]\",\n            \"data-[swipe-direction=up]:inset-x-0 data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:max-h-[85dvh] data-[swipe-direction=up]:[transform:translateY(var(--drawer-swipe-movement-y,0px))] data-[swipe-direction=up]:rounded-b-xl data-[swipe-direction=up]:border-b data-[swipe-direction=up]:border-border data-[swipe-direction=up]:pt-[env(safe-area-inset-top)] data-[swipe-direction=up]:data-ending-style:[transform:translateY(-100%)] data-[swipe-direction=up]:data-starting-style:[transform:translateY(-100%)]\",\n            \"data-[swipe-direction=right]:inset-y-0 data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:w-3/4 data-[swipe-direction=right]:max-w-sm data-[swipe-direction=right]:[transform:translateX(var(--drawer-swipe-movement-x,0px))] data-[swipe-direction=right]:border-l data-[swipe-direction=right]:border-border data-[swipe-direction=right]:data-ending-style:[transform:translateX(100%)] data-[swipe-direction=right]:data-starting-style:[transform:translateX(100%)]\",\n            \"data-[swipe-direction=left]:inset-y-0 data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:w-3/4 data-[swipe-direction=left]:max-w-sm data-[swipe-direction=left]:[transform:translateX(var(--drawer-swipe-movement-x,0px))] data-[swipe-direction=left]:border-r data-[swipe-direction=left]:border-border data-[swipe-direction=left]:data-ending-style:[transform:translateX(-100%)] data-[swipe-direction=left]:data-starting-style:[transform:translateX(-100%)]\",\n            className\n          )}\n          {...props}\n        >\n          {children}\n          {showCloseButton ? (\n            <SheetPrimitive.Close\n              data-slot=\"sheet-close\"\n              render={\n                <Button\n                  variant=\"ghost\"\n                  size=\"icon-sm\"\n                  className=\"absolute top-3 right-3\"\n                  aria-label=\"Close\"\n                />\n              }\n            >\n              <XIcon />\n            </SheetPrimitive.Close>\n          ) : null}\n        </SheetPrimitive.Popup>\n      </SheetPrimitive.Viewport>\n    </SheetPrimitive.Portal>\n  )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"sheet-header\"\n      className={cn(\"flex flex-col gap-1 p-4 pr-12\", className)}\n      {...props}\n    />\n  )\n}\n\n/*\n * Drawer.Content marks the part people read and select, so dragging across\n * text here selects it instead of swiping the sheet away.\n */\nfunction SheetBody({ className, ...props }: SheetPrimitive.Content.Props) {\n  return (\n    <SheetPrimitive.Content\n      data-slot=\"sheet-body\"\n      className={cn(\"flex-1 overflow-y-auto px-4\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"sheet-footer\"\n      className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n  return (\n    <SheetPrimitive.Title\n      data-slot=\"sheet-title\"\n      className={cn(\"text-base font-medium text-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction SheetDescription({\n  className,\n  ...props\n}: SheetPrimitive.Description.Props) {\n  return (\n    <SheetPrimitive.Description\n      data-slot=\"sheet-description\"\n      className={cn(\"text-sm text-muted-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Sheet,\n  SheetBody,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n  SheetTrigger,\n}\nexport type { SheetSide }\n",
      "type": "registry:ui"
    }
  ],
  "cssVars": {
    "theme": {
      "color-backdrop": "var(--backdrop)"
    },
    "light": {
      "backdrop": "color-mix(in oklch, var(--color-neutral-950) 20%, transparent)"
    },
    "dark": {
      "backdrop": "color-mix(in oklch, var(--color-black) 60%, transparent)"
    }
  },
  "meta": {
    "tier": "base-components",
    "group": "Overlays",
    "docs": "https://fibo.toribryan.com/?path=/docs/base-components-overlays-sheet--docs"
  },
  "docs": "Docs and live examples: https://fibo.toribryan.com/?path=/docs/base-components-overlays-sheet--docs",
  "categories": [
    "base-components",
    "overlays"
  ],
  "type": "registry:ui"
}