Components
Loading preview...
HeroUI v3 Modal — compound dialog/overlay with placements, backdrops, sizes, dismiss behavior, scroll behavior, controlled state and forms.
@reapollo
npx shadcn@latest add https://21st.dev/r/larsen66/heroui-modal"use client"
import { ArrowUpFromLine, Sparkles } from "lucide-react"
import { Button } from "@heroui/react"
import React from "react"
import { Modal } from "@/components/ui/heroui-modal"
const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
"arrow-up-from-line": ArrowUpFromLine,
sparkles: Sparkles,
}
export default function CustomAnimations() {
const animations = [
{
classNames: {
backdrop: [
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:zoom-in-95",
"data-[entering]:duration-400",
"data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:zoom-out-95",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]",
].join(" "),
},
description:
"Physics-based elastic scaling. Simulates a high-damping spring system with fast transient response and prolonged settling time. Ideal for Modals and Popovers.",
icon: "sparkles",
name: "Kinematic Scale",
},
{
classNames: {
backdrop: [
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
container: [
"data-[entering]:animate-in",
"data-[entering]:fade-in-0",
"data-[entering]:slide-in-from-bottom-4",
"data-[entering]:duration-500",
"data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]",
"data-[exiting]:animate-out",
"data-[exiting]:fade-out-0",
"data-[exiting]:slide-out-to-bottom-2",
"data-[exiting]:duration-200",
"data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]",
].join(" "),
},
description:
"Simulates movement through a medium with fluid resistance. Eliminates mechanical linearity for a natural, grounded feel. Perfect for Bottom Sheets or Toasts.",
icon: "arrow-up-from-line",
name: "Fluid Slide",
},
]
return (
<div className="flex flex-wrap gap-4">
{animations.map(({ classNames, description, icon, name }) => {
const IconComponent = iconMap[icon]
return (
<Modal key={name}>
<Button variant="secondary">{name}</Button>
<Modal.Backdrop className={classNames.backdrop}>
<Modal.Container className={classNames.container}>
<Modal.Dialog className="sm:max-w-[360px]">
<Modal.CloseTrigger />
<Modal.Header>
<Modal.Icon className="bg-default text-foreground">
{!!IconComponent && <IconComponent className="size-5" />}
</Modal.Icon>
<Modal.Heading>{name} Animation</Modal.Heading>
</Modal.Header>
<Modal.Body>
<p className="mt-1">{description}</p>
</Modal.Body>
<Modal.Footer>
<Button slot="close" variant="tertiary">
Close
</Button>
<Button slot="close">Try Again</Button>
</Modal.Footer>
</Modal.Dialog>
</Modal.Container>
</Modal.Backdrop>
</Modal>
)
})}
</div>
)
}