Files
codeaashu-claude-code/web/components/ui/dialog.tsx
ashutoshpythoncs@gmail.com b564857c0b claude-code
2026-03-31 18:58:05 +05:30

132 lines
3.8 KiB
TypeScript

'use client'
import * as React from 'react'
import * as RadixDialog from '@radix-ui/react-dialog'
import { X } from 'lucide-react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const dialogContentVariants = cva(
[
'relative z-50 grid w-full gap-4 rounded-lg border border-surface-700',
'bg-surface-900 p-6 shadow-lg',
'data-[state=open]:animate-scale-in data-[state=closed]:animate-scale-out',
].join(' '),
{
variants: {
size: {
sm: 'max-w-sm',
md: 'max-w-lg',
lg: 'max-w-2xl',
full: 'max-w-[calc(100vw-2rem)] h-[calc(100vh-4rem)]',
},
},
defaultVariants: {
size: 'md',
},
}
)
const Dialog = RadixDialog.Root
const DialogTrigger = RadixDialog.Trigger
const DialogPortal = RadixDialog.Portal
const DialogClose = RadixDialog.Close
const DialogOverlay = React.forwardRef<
React.ElementRef<typeof RadixDialog.Overlay>,
React.ComponentPropsWithoutRef<typeof RadixDialog.Overlay>
>(({ className, ...props }, ref) => (
<RadixDialog.Overlay
ref={ref}
className={cn(
'fixed inset-0 z-50 bg-black/60 backdrop-blur-sm',
'data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out',
className
)}
{...props}
/>
))
DialogOverlay.displayName = RadixDialog.Overlay.displayName
interface DialogContentProps
extends React.ComponentPropsWithoutRef<typeof RadixDialog.Content>,
VariantProps<typeof dialogContentVariants> {
showClose?: boolean
}
const DialogContent = React.forwardRef<
React.ElementRef<typeof RadixDialog.Content>,
DialogContentProps
>(({ className, children, size, showClose = true, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<RadixDialog.Content
ref={ref}
className={cn(
'fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]',
dialogContentVariants({ size, className })
)}
{...props}
>
{children}
{showClose && (
<DialogClose className="absolute right-4 top-4 rounded-sm text-surface-500 hover:text-surface-100 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
<X className="h-4 w-4" aria-hidden="true" />
<span className="sr-only">Close</span>
</DialogClose>
)}
</RadixDialog.Content>
</DialogPortal>
))
DialogContent.displayName = RadixDialog.Content.displayName
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div className={cn('flex flex-col gap-1.5', className)} {...props} />
)
DialogHeader.displayName = 'DialogHeader'
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
{...props}
/>
)
DialogFooter.displayName = 'DialogFooter'
const DialogTitle = React.forwardRef<
React.ElementRef<typeof RadixDialog.Title>,
React.ComponentPropsWithoutRef<typeof RadixDialog.Title>
>(({ className, ...props }, ref) => (
<RadixDialog.Title
ref={ref}
className={cn('text-lg font-semibold text-surface-50', className)}
{...props}
/>
))
DialogTitle.displayName = RadixDialog.Title.displayName
const DialogDescription = React.forwardRef<
React.ElementRef<typeof RadixDialog.Description>,
React.ComponentPropsWithoutRef<typeof RadixDialog.Description>
>(({ className, ...props }, ref) => (
<RadixDialog.Description
ref={ref}
className={cn('text-sm text-surface-400', className)}
{...props}
/>
))
DialogDescription.displayName = RadixDialog.Description.displayName
export {
Dialog,
DialogTrigger,
DialogPortal,
DialogOverlay,
DialogClose,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
}