sheet.tsx raw

   1  "use client";
   2  
   3  import * as React from "react";
   4  import { XIcon } from "lucide-react";
   5  import { Dialog as SheetPrimitive } from "radix-ui";
   6  
   7  import { cn } from "src/lib/utils";
   8  
   9  function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
  10    return <SheetPrimitive.Root data-slot="sheet" {...props} />;
  11  }
  12  
  13  function SheetTrigger({
  14    ...props
  15  }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
  16    return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
  17  }
  18  
  19  function SheetClose({
  20    ...props
  21  }: React.ComponentProps<typeof SheetPrimitive.Close>) {
  22    return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
  23  }
  24  
  25  function SheetPortal({
  26    ...props
  27  }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
  28    return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
  29  }
  30  
  31  function SheetOverlay({
  32    className,
  33    ...props
  34  }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
  35    return (
  36      <SheetPrimitive.Overlay
  37        data-slot="sheet-overlay"
  38        className={cn(
  39          "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
  40          className
  41        )}
  42        {...props}
  43      />
  44    );
  45  }
  46  
  47  function SheetContent({
  48    className,
  49    children,
  50    side = "right",
  51    showCloseButton = true,
  52    ...props
  53  }: React.ComponentProps<typeof SheetPrimitive.Content> & {
  54    side?: "top" | "right" | "bottom" | "left";
  55    showCloseButton?: boolean;
  56  }) {
  57    return (
  58      <SheetPortal>
  59        <SheetOverlay />
  60        <SheetPrimitive.Content
  61          data-slot="sheet-content"
  62          className={cn(
  63            "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:animate-in data-[state=open]:duration-500",
  64            side === "right" &&
  65              "inset-y-0 right-0 h-full max-h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
  66            side === "left" &&
  67              "inset-y-0 left-0 h-full max-h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
  68            side === "top" &&
  69              "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
  70            side === "bottom" &&
  71              "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
  72            className
  73          )}
  74          {...props}
  75        >
  76          {children}
  77          {showCloseButton && (
  78            <SheetPrimitive.Close className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary">
  79              <XIcon className="size-4" />
  80              <span className="sr-only">Close</span>
  81            </SheetPrimitive.Close>
  82          )}
  83        </SheetPrimitive.Content>
  84      </SheetPortal>
  85    );
  86  }
  87  
  88  function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
  89    return (
  90      <div
  91        data-slot="sheet-header"
  92        className={cn("flex flex-col gap-1.5 p-4", className)}
  93        {...props}
  94      />
  95    );
  96  }
  97  
  98  function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
  99    return (
 100      <div
 101        data-slot="sheet-footer"
 102        className={cn("mt-auto flex flex-col gap-2 p-4", className)}
 103        {...props}
 104      />
 105    );
 106  }
 107  
 108  function SheetTitle({
 109    className,
 110    ...props
 111  }: React.ComponentProps<typeof SheetPrimitive.Title>) {
 112    return (
 113      <SheetPrimitive.Title
 114        data-slot="sheet-title"
 115        className={cn("font-semibold text-foreground", className)}
 116        {...props}
 117      />
 118    );
 119  }
 120  
 121  function SheetDescription({
 122    className,
 123    ...props
 124  }: React.ComponentProps<typeof SheetPrimitive.Description>) {
 125    return (
 126      <SheetPrimitive.Description
 127        data-slot="sheet-description"
 128        className={cn("text-sm text-muted-foreground", className)}
 129        {...props}
 130      />
 131    );
 132  }
 133  
 134  export {
 135    Sheet,
 136    SheetTrigger,
 137    SheetClose,
 138    SheetContent,
 139    SheetHeader,
 140    SheetFooter,
 141    SheetTitle,
 142    SheetDescription,
 143  };
 144