--- title: Dialog description: A modal window overlaid on the primary window, rendering content that requires user interaction. --- ## Installation CLI Manual ```bash npx lightswind@latest add dialog ``` Copy and paste the following code into your project. ```tsx import * as React from "react"; import * as ReactDOM from "react-dom"; import { cn } from "@/components/lib/utils"; // Assuming a utility for classnames import { X } from "lucide-react"; import { motion, AnimatePresence, HTMLMotionProps } from "framer-motion"; // Helper for cn if not provided const dummyCn = (...inputs) => { return inputs.filter(Boolean).join(' '); }; const cnFunction = typeof cn !== 'undefined' ? cn : dummyCn; interface DialogContextType { open: boolean; setOpen: React.Dispatch>; } const DialogContext = React.createContext(undefined); interface DialogProps { children: React.ReactNode; defaultOpen?: boolean; open?: boolean; onOpenChange?: (open: boolean) => void; } const Dialog: React.FC = ({ children, defaultOpen = false, open: controlledOpen, onOpenChange, }) => { const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen); const isControlled = controlledOpen !== undefined; const open = isControlled ? controlledOpen : uncontrolledOpen; const setOpen = React.useCallback((value: boolean | ((prev: boolean) => boolean)) => { if (!isControlled) { setUncontrolledOpen(value); } if (onOpenChange) { const newValue = typeof value === "function" ? value(open) : value; onOpenChange(newValue); } }, [isControlled, onOpenChange, open]); return ( {children} ); }; interface DialogTriggerProps { children: React.ReactNode; asChild?: boolean; } const DialogTrigger = React.forwardRef>( ({ children, asChild = false, ...props }, ref) => { const context = React.useContext(DialogContext); if (!context) { throw new Error("DialogTrigger must be used within a Dialog"); } const { setOpen } = context; const handleClick = (e: React.MouseEvent) => { e.preventDefault(); setOpen(true); if (props.onClick) { props.onClick(e); } }; const { onClick, ...otherProps } = props; if (asChild) { return (
{React.Children.map(children, child => { if (React.isValidElement(child)) { const element = child as React.ReactElement; return React.cloneElement(element, { ...element.props }); } return child; })}
); } return (
{children}
); } ); DialogTrigger.displayName = "DialogTrigger"; type OmittedDialogContentHTMLAttributes = Omit, 'onAnimationStart' | 'onAnimationEnd' | 'onAnimationIteration' | 'onTransitionEnd' | 'onDrag' | 'onDragEnd' | 'onDragEnter' | 'onDragExit' | 'onDragLeave' | 'onDragOver' | 'onDragStart' | 'onDrop' | 'onMouseDown' | 'onMouseEnter' | 'onMouseLeave' | 'onMouseMove' | 'onMouseOut' | 'onMouseOver' | 'onMouseUp' | 'onTouchCancel' | 'onTouchEnd' | 'onTouchMove' | 'onTouchStart' | 'onPointerDown' | 'onPointerMove' | 'onPointerUp' | 'onPointerCancel' | 'onPointerEnter' | 'onPointerLeave' | 'onPointerOver' | 'onPointerOut' | 'onGotPointerCapture' | 'onLostPointerCapture' >; // Define Props Interface interface DialogContentProps extends OmittedDialogContentHTMLAttributes { hideCloseButton?: boolean; } const DialogContent = React.forwardRef( ({ className, children, hideCloseButton, ...props }, ref) => { const context = React.useContext(DialogContext); if (!context) { throw new Error("DialogContent must be used within a Dialog"); } const { open, setOpen } = context; const [mounted, setMounted] = React.useState(false); React.useEffect(() => { setMounted(true); }, []); React.useEffect(() => { if (open) { document.body.style.overflow = "hidden"; } else { document.body.style.overflow = ""; } return () => { document.body.style.overflow = ""; }; }, [open]); if (!mounted) return null; return ReactDOM.createPortal( {open && (
{/* Backdrop Overlay */} setOpen(false)} /> {/* Dialog Content */} } > {children} {!hideCloseButton && ( )}
)}
, document.body ); } ); DialogContent.displayName = "DialogContent"; const DialogHeader = React.forwardRef>( ({ className, ...props }, ref) => (
) ); DialogHeader.displayName = "DialogHeader"; const DialogTitle = React.forwardRef>( ({ className, ...props }, ref) => (

) ); DialogTitle.displayName = "DialogTitle"; const DialogDescription = React.forwardRef>( ({ className, ...props }, ref) => (

) ); DialogDescription.displayName = "DialogDescription"; const DialogFooter = React.forwardRef>( ({ className, ...props }, ref) => (

) ); DialogFooter.displayName = "DialogFooter"; const DialogClose = React.forwardRef>( ({ className, ...props }, ref) => { const context = React.useContext(DialogContext); const setOpen = context ? context.setOpen : () => { }; return ( Dialog Title Dialog Description ```