dialog.tsx 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import * as DialogPrimitive from '@radix-ui/react-dialog';
  2. import { XIcon } from 'lucide-react';
  3. import * as React from 'react';
  4. import { cn } from '@/common/helpers/cn';
  5. function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
  6. return <DialogPrimitive.Root data-slot="dialog" {...props} />;
  7. }
  8. function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
  9. return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
  10. }
  11. function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
  12. return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
  13. }
  14. function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
  15. return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
  16. }
  17. function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
  18. return (
  19. <DialogPrimitive.Overlay
  20. data-slot="dialog-overlay"
  21. className={cn(
  22. 'fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
  23. className,
  24. )}
  25. {...props}
  26. />
  27. );
  28. }
  29. function DialogContent({ className, children, ...props }: React.ComponentProps<typeof DialogPrimitive.Content>) {
  30. return (
  31. <DialogPortal data-slot="dialog-portal">
  32. <DialogOverlay />
  33. <DialogPrimitive.Content
  34. data-slot="dialog-content"
  35. className={cn(
  36. '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 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',
  37. className,
  38. )}
  39. {...props}
  40. >
  41. {children}
  42. <DialogPrimitive.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-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
  43. <XIcon />
  44. <span className="sr-only">Close</span>
  45. </DialogPrimitive.Close>
  46. </DialogPrimitive.Content>
  47. </DialogPortal>
  48. );
  49. }
  50. function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
  51. return <div data-slot="dialog-header" className={cn('flex flex-col gap-2 text-center sm:text-left', className)} {...props} />;
  52. }
  53. function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
  54. return <div data-slot="dialog-footer" className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)} {...props} />;
  55. }
  56. function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
  57. return <DialogPrimitive.Title data-slot="dialog-title" className={cn('text-lg leading-none font-semibold', className)} {...props} />;
  58. }
  59. function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {
  60. return <DialogPrimitive.Description data-slot="dialog-description" className={cn('text-sm text-muted-foreground', className)} {...props} />;
  61. }
  62. export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger };