dialog.tsx raw

   1  "use client";
   2  
   3  import * as React from "react";
   4  import { XIcon } from "lucide-react";
   5  import { Dialog as DialogPrimitive } from "radix-ui";
   6  
   7  import { cn } from "src/lib/utils";
   8  import { Button } from "src/components/ui/button";
   9  
  10  function Dialog({
  11    ...props
  12  }: React.ComponentProps<typeof DialogPrimitive.Root>) {
  13    return <DialogPrimitive.Root data-slot="dialog" {...props} />;
  14  }
  15  
  16  function DialogTrigger({
  17    ...props
  18  }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
  19    return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
  20  }
  21  
  22  function DialogPortal({
  23    ...props
  24  }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
  25    return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
  26  }
  27  
  28  function DialogClose({
  29    ...props
  30  }: React.ComponentProps<typeof DialogPrimitive.Close>) {
  31    return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
  32  }
  33  
  34  function DialogOverlay({
  35    className,
  36    ...props
  37  }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
  38    return (
  39      <DialogPrimitive.Overlay
  40        data-slot="dialog-overlay"
  41        className={cn(
  42          "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",
  43          className
  44        )}
  45        {...props}
  46      />
  47    );
  48  }
  49  
  50  function DialogContent({
  51    className,
  52    children,
  53    showCloseButton = true,
  54    ...props
  55  }: React.ComponentProps<typeof DialogPrimitive.Content> & {
  56    showCloseButton?: boolean;
  57  }) {
  58    return (
  59      <DialogPortal data-slot="dialog-portal">
  60        <DialogOverlay />
  61        <DialogPrimitive.Content
  62          data-slot="dialog-content"
  63          className={cn(
  64            "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
  65            className
  66          )}
  67          {...props}
  68        >
  69          {children}
  70          {showCloseButton && (
  71            <DialogPrimitive.Close
  72              data-slot="dialog-close"
  73              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-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
  74            >
  75              <XIcon />
  76              <span className="sr-only">Close</span>
  77            </DialogPrimitive.Close>
  78          )}
  79        </DialogPrimitive.Content>
  80      </DialogPortal>
  81    );
  82  }
  83  
  84  function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
  85    return (
  86      <div
  87        data-slot="dialog-header"
  88        className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
  89        {...props}
  90      />
  91    );
  92  }
  93  
  94  function DialogFooter({
  95    className,
  96    showCloseButton = false,
  97    children,
  98    ...props
  99  }: React.ComponentProps<"div"> & {
 100    showCloseButton?: boolean;
 101  }) {
 102    return (
 103      <div
 104        data-slot="dialog-footer"
 105        className={cn(
 106          "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
 107          className
 108        )}
 109        {...props}
 110      >
 111        {children}
 112        {showCloseButton && (
 113          <DialogPrimitive.Close asChild>
 114            <Button variant="outline">Close</Button>
 115          </DialogPrimitive.Close>
 116        )}
 117      </div>
 118    );
 119  }
 120  
 121  function DialogTitle({
 122    className,
 123    ...props
 124  }: React.ComponentProps<typeof DialogPrimitive.Title>) {
 125    return (
 126      <DialogPrimitive.Title
 127        data-slot="dialog-title"
 128        className={cn("text-lg leading-none font-semibold", className)}
 129        {...props}
 130      />
 131    );
 132  }
 133  
 134  function DialogDescription({
 135    className,
 136    ...props
 137  }: React.ComponentProps<typeof DialogPrimitive.Description>) {
 138    return (
 139      <DialogPrimitive.Description
 140        data-slot="dialog-description"
 141        className={cn("text-sm text-muted-foreground", className)}
 142        {...props}
 143      />
 144    );
 145  }
 146  
 147  export {
 148    Dialog,
 149    DialogClose,
 150    DialogContent,
 151    DialogDescription,
 152    DialogFooter,
 153    DialogHeader,
 154    DialogOverlay,
 155    DialogPortal,
 156    DialogTitle,
 157    DialogTrigger,
 158  };
 159