corr
componentanimated-dialogsource: ok · hit
Animated Dialog
A dialog wrapper with subtle Motion transitions for confirmation and form flows.
npx shadcn add "https://ui.corr.sh/r/animated-dialog.json"free
Interaction
modal
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightRegistry dependencies
buttondialog
Files1 · source cached 10/8/2026, 7:45:30 PM
registry/corr/components/animated-dialog.tsx
"use client"
import type { ReactNode } from "react"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { cn } from "@/lib/utils"
export type AnimatedDialogAnimation =
| "zoom"
| "slide-from-left"
| "slide-from-right"
| "slide-from-top"
| "slide-from-bottom"
const animationClassName: Record<AnimatedDialogAnimation, string> = {
zoom:
"transition-none! data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-open:duration-300 data-closed:duration-150",
"slide-from-left":
"transition-none! data-open:animate-in data-open:fade-in-0 data-open:zoom-in-100 data-open:slide-in-from-left-8 data-closed:animate-out data-closed:fade-out-0 data-closed:slide-out-to-left-6 data-open:duration-300 data-closed:duration-150",
"slide-from-right":
"transition-none! data-open:animate-in data-open:fade-in-0 data-open:zoom-in-100 data-open:slide-in-from-right-8 data-closed:animate-out data-closed:fade-out-0 data-closed:slide-out-to-right-6 data-open:duration-300 data-closed:duration-150",
"slide-from-top":
"transition-none! data-open:animate-in data-open:fade-in-0 data-open:zoom-in-100 data-open:slide-in-from-top-8 data-closed:animate-out data-closed:fade-out-0 data-closed:slide-out-to-top-6 data-open:duration-300 data-closed:duration-150",
"slide-from-bottom":
"transition-none! data-open:animate-in data-open:fade-in-0 data-open:zoom-in-100 data-open:slide-in-from-bottom-8 data-closed:animate-out data-closed:fade-out-0 data-closed:slide-out-to-bottom-6 data-open:duration-300 data-closed:duration-150",
}
export function AnimatedDialog({
trigger,
title,
description,
children,
actionLabel = "Continue",
cancelLabel = "Cancel",
animation = "zoom",
className,
onAction,
}: {
trigger: ReactNode
title: string
description?: string
children?: ReactNode
actionLabel?: string
cancelLabel?: string
animation?: AnimatedDialogAnimation
className?: string
onAction?: () => void
}) {
return (
<Dialog>
<DialogTrigger asChild>{trigger}</DialogTrigger>
<DialogContent
className={cn(
"sm:max-w-[425px]",
animationClassName[animation],
className
)}
>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
{description ? (
<DialogDescription>{description}</DialogDescription>
) : null}
</DialogHeader>
{children ? <div className="text-sm">{children}</div> : null}
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">{cancelLabel}</Button>
</DialogClose>
<DialogClose asChild>
<Button onClick={onAction}>{actionLabel}</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
)
}