An impactful dialog that ensures your important messages and actions get the attention they deserve! 💬✨
Copynpm install @radix-ui/react-dialog @radix-ui/react-visually-hidden tailwindcss-animate
npm install @radix-ui/react-dialog @radix-ui/react-visually-hidden tailwindcss-animate
tailwind.config.ts
Copy{ content: [...], theme: [...], // add plugin plugins: [require("tailwindcss-animate")], }
{ content: [...], theme: [...], // add plugin plugins: [require("tailwindcss-animate")], }
Copy"use client"; import * as ReactDialog from "@radix-ui/react-dialog"; import { cn } from "@/lib/utils"; import { cva, VariantProps } from "class-variance-authority"; import React, { HTMLAttributes, ReactNode } from "react"; import { VisuallyHidden } from "@radix-ui/react-visually-hidden"; import { X } from "lucide-react"; const Dialog = ReactDialog.Root; const DialogTrigger = ReactDialog.Trigger; const overlayVariants = cva( ` fixed bg-black/80 font-head data-[state=open]:fade-in-0 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 `, { variants: { variant: { default: "inset-0 z-50 bg-black/80", none: "fixed bg-transparent", }, }, defaultVariants: { variant: "default", }, } ); interface IDialogBackgroupProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof overlayVariants> {} const DialogBackdrop = React.forwardRef<HTMLDivElement, IDialogBackgroupProps>( (inputProps: IDialogBackgroupProps, forwardedRef) => { const { variant = "default", className, ...props } = inputProps; return ( <ReactDialog.Overlay className={cn(overlayVariants({ variant }), className)} {...props} /> ); } ); const dialogVariants = cva( `fixed z-50 left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col border-2 border-black shadow-md gap-4 overflow-y-auto bg-white w-full h-fit max-h-[80vh] max-w-[97%] duration-300 data-[state=open]:animate-in data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-[48%] data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:zoom-out-95`, { variants: { size: { auto: "max-w-fit", sm: "lg:max-w-[30%]", md: "lg:max-w-[40%]", lg: "lg:max-w-[50%]", xl: "lg:max-w-[60%]", "2xl": "lg:max-w-[70%]", "3xl": "lg:max-w-[80%]", "4xl": "lg:max-w-[90%]", screen: "max-w-[100%]", }, }, defaultVariants: { size: "auto", }, } ); interface IDialogContentProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogVariants> { overlay?: IDialogBackgroupProps; } const DialogContent = React.forwardRef<HTMLDivElement, IDialogContentProps>( (inputProps: IDialogContentProps, forwardedRef) => { const { children, size = "auto", className, overlay, ...props } = inputProps; return ( <ReactDialog.Portal> <DialogBackdrop {...overlay} /> <ReactDialog.Content className={cn(dialogVariants({ size }), className)} ref={forwardedRef} {...props} > <VisuallyHidden> <ReactDialog.Title /> </VisuallyHidden> <div className="flex flex-col relative">{children}</div> </ReactDialog.Content> </ReactDialog.Portal> ); } ); interface IDialogDescriptionProps extends HTMLAttributes<HTMLDivElement> {} const DialogDescription = ({ children, className, ...props }: IDialogDescriptionProps) => { return ( <ReactDialog.Description className={cn(className)} {...props}> {children} </ReactDialog.Description> ); }; const dialogFooterVariants = cva( "flex items-center justify-end border-t-2 border-black min-h-12 gap-4 px-4 py-2", { variants: { variant: { default: "bg-white text-black", }, position: { fixed: "sticky bottom-0", static: "static", }, }, defaultVariants: { position: "fixed", }, } ); export interface IDialogFooterProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogFooterVariants> {} const DialogFooter = ({ children, className, position, variant, ...props }: IDialogFooterProps) => { return ( <div className={cn(dialogFooterVariants({ position, variant }), className)} {...props} > {children} </div> ); }; const dialogHeaderVariants = cva( "flex items-center justify-between border-b-2 border-black px-4 min-h-12", { variants: { variant: { default: "bg-primary-400 text-black", }, position: { fixed: "sticky top-0", static: "static", }, }, defaultVariants: { variant: "default", position: "static", }, } ); const DialogHeaderDefaultLayout = ({ children }: { children: ReactNode }) => { return ( <> {children} <DialogTrigger title="Close pop-up" className="cursor-pointer" asChild> <X /> </DialogTrigger> </> ); }; interface IDialogHeaderProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogHeaderVariants>, ReactDialog.DialogTitleProps {} const DialogHeader = ({ children, className, position, variant, asChild, ...props }: IDialogHeaderProps) => { return ( <div className={cn(dialogHeaderVariants({ position, variant }), className)} {...props} > {asChild ? ( children ) : ( <DialogHeaderDefaultLayout>{children}</DialogHeaderDefaultLayout> )} </div> ); }; const DialogComponent = Object.assign(Dialog, { Trigger: DialogTrigger, Header: DialogHeader, Content: DialogContent, Description: DialogDescription, Footer: DialogFooter, }); export { DialogComponent as Dialog };
"use client"; import * as ReactDialog from "@radix-ui/react-dialog"; import { cn } from "@/lib/utils"; import { cva, VariantProps } from "class-variance-authority"; import React, { HTMLAttributes, ReactNode } from "react"; import { VisuallyHidden } from "@radix-ui/react-visually-hidden"; import { X } from "lucide-react"; const Dialog = ReactDialog.Root; const DialogTrigger = ReactDialog.Trigger; const overlayVariants = cva( ` fixed bg-black/80 font-head data-[state=open]:fade-in-0 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 `, { variants: { variant: { default: "inset-0 z-50 bg-black/80", none: "fixed bg-transparent", }, }, defaultVariants: { variant: "default", }, } ); interface IDialogBackgroupProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof overlayVariants> {} const DialogBackdrop = React.forwardRef<HTMLDivElement, IDialogBackgroupProps>( (inputProps: IDialogBackgroupProps, forwardedRef) => { const { variant = "default", className, ...props } = inputProps; return ( <ReactDialog.Overlay className={cn(overlayVariants({ variant }), className)} {...props} /> ); } ); const dialogVariants = cva( `fixed z-50 left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col border-2 border-black shadow-md gap-4 overflow-y-auto bg-white w-full h-fit max-h-[80vh] max-w-[97%] duration-300 data-[state=open]:animate-in data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-[48%] data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:zoom-out-95`, { variants: { size: { auto: "max-w-fit", sm: "lg:max-w-[30%]", md: "lg:max-w-[40%]", lg: "lg:max-w-[50%]", xl: "lg:max-w-[60%]", "2xl": "lg:max-w-[70%]", "3xl": "lg:max-w-[80%]", "4xl": "lg:max-w-[90%]", screen: "max-w-[100%]", }, }, defaultVariants: { size: "auto", }, } ); interface IDialogContentProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogVariants> { overlay?: IDialogBackgroupProps; } const DialogContent = React.forwardRef<HTMLDivElement, IDialogContentProps>( (inputProps: IDialogContentProps, forwardedRef) => { const { children, size = "auto", className, overlay, ...props } = inputProps; return ( <ReactDialog.Portal> <DialogBackdrop {...overlay} /> <ReactDialog.Content className={cn(dialogVariants({ size }), className)} ref={forwardedRef} {...props} > <VisuallyHidden> <ReactDialog.Title /> </VisuallyHidden> <div className="flex flex-col relative">{children}</div> </ReactDialog.Content> </ReactDialog.Portal> ); } ); interface IDialogDescriptionProps extends HTMLAttributes<HTMLDivElement> {} const DialogDescription = ({ children, className, ...props }: IDialogDescriptionProps) => { return ( <ReactDialog.Description className={cn(className)} {...props}> {children} </ReactDialog.Description> ); }; const dialogFooterVariants = cva( "flex items-center justify-end border-t-2 border-black min-h-12 gap-4 px-4 py-2", { variants: { variant: { default: "bg-white text-black", }, position: { fixed: "sticky bottom-0", static: "static", }, }, defaultVariants: { position: "fixed", }, } ); export interface IDialogFooterProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogFooterVariants> {} const DialogFooter = ({ children, className, position, variant, ...props }: IDialogFooterProps) => { return ( <div className={cn(dialogFooterVariants({ position, variant }), className)} {...props} > {children} </div> ); }; const dialogHeaderVariants = cva( "flex items-center justify-between border-b-2 border-black px-4 min-h-12", { variants: { variant: { default: "bg-primary-400 text-black", }, position: { fixed: "sticky top-0", static: "static", }, }, defaultVariants: { variant: "default", position: "static", }, } ); const DialogHeaderDefaultLayout = ({ children }: { children: ReactNode }) => { return ( <> {children} <DialogTrigger title="Close pop-up" className="cursor-pointer" asChild> <X /> </DialogTrigger> </> ); }; interface IDialogHeaderProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dialogHeaderVariants>, ReactDialog.DialogTitleProps {} const DialogHeader = ({ children, className, position, variant, asChild, ...props }: IDialogHeaderProps) => { return ( <div className={cn(dialogHeaderVariants({ position, variant }), className)} {...props} > {asChild ? ( children ) : ( <DialogHeaderDefaultLayout>{children}</DialogHeaderDefaultLayout> )} </div> ); }; const DialogComponent = Object.assign(Dialog, { Trigger: DialogTrigger, Header: DialogHeader, Content: DialogContent, Description: DialogDescription, Footer: DialogFooter, }); export { DialogComponent as Dialog };
size
For customize anything on dialog you can change className for the component and doas you want.
className
Last Updated: 04 Nov, 2024