Components
Loading preview...
A dot background that expands on hover, as seen on Clerk's website Features: - Animated Reveal: Smooth animations grab users' attention as content pops up. - Customizable Speed: Tweak the animation speed to match the vibe you want. - Color and Opacity Control: Play around with colors and opacities for cool visual effects. - Dot Matrix Effect: Add a modern, techy look with a dot matrix pattern. - Gradient Overlay: Use an optional gradient overlay for extra visual depth. - Responsive Design: Fits perfectly on any screen size for a consistent experience. Example Use Cases: - Call to Action on Landing Page: Use fun animations to highlight important actions or offers. - Cards on Landing Page: Make card displays pop with dynamic reveal effects to showcase key info.
@aceternity
npx shadcn@latest add https://21st.dev/r/aceternity/canvas-reveal-effect"use client";
import React from "react";
import { AnimatePresence, motion } from "framer-motion";
import { CanvasRevealEffect } from "@/components/ui/canvas-reveal-effect";
function DemoWithCards() {
return (
<>
<div className="py-20 flex flex-col lg:flex-row items-center justify-center bg-white dark:bg-black w-full gap-4 mx-auto px-8">
<Card title="Sheetal is Nisha" icon={<AceternityIcon />}>
<CanvasRevealEffect
animationSpeed={5.1}
containerClassName="bg-emerald-900"
/>
</Card>
<Card title="Nisha is Munni" icon={<AceternityIcon />}>
<CanvasRevealEffect
animationSpeed={3}
containerClassName="bg-black"
colors={[
[236, 72, 153],
[232, 121, 249],
]}
dotSize={2}
/>
<div className="absolute inset-0 [mask-image:radial-gradient(400px_at_center,white,transparent)] bg-black/50 dark:bg-black/90" />
</Card>
<Card title="Munni is Aditi" icon={<AceternityIcon />}>
<CanvasRevealEffect
animationSpeed={3}
containerClassName="bg-sky-600"
colors={[[125, 211, 252]]}
/>
</Card>
</div>
</>
);
}
function StaticDemo() {
return (
<>
<div className="py-20 flex flex-col lg:flex-row items-center justify-center bg-white dark:bg-black w-full gap-4 mx-auto px-8">
<div className="border border-black/[0.2] group/canvas-card flex items-center justify-center dark:border-white/[0.2] max-w-sm w-full mx-auto p-4 relative h-[30rem] relative">
<Icon className="absolute h-6 w-6 -top-3 -left-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -bottom-3 -left-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -top-3 -right-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -bottom-3 -right-3 dark:text-white text-black" />
<AnimatePresence>
<div className="h-full w-full absolute inset-0">
<CanvasRevealEffect
animationSpeed={3}
containerClassName="bg-black"
colors={[
[236, 72, 153],
[232, 121, 249],
]}
dotSize={2}
/>
</div>
</AnimatePresence>
<div className="relative z-20">
<div className="text-center group-hover/canvas-card:-translate-y-4 group-hover/canvas-card:opacity-0 transition duration-200 w-full mx-auto flex items-center justify-center">
<AceternityIcon />
</div>
<h2 className="dark:text-white text-xl opacity-0 group-hover/canvas-card:opacity-100 relative z-10 text-black mt-4 font-bold group-hover/canvas-card:text-white group-hover/canvas-card:-translate-y-2 transition duration-200">
I'm static and I know it.
</h2>
</div>
</div>
</div>
</>
);
}
function SectionDemo() {
const [hovered, setHovered] = React.useState(false);
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className="h-[40rem] flex flex-col lg:flex-row overflow-hidden items-center justify-center bg-black w-full gap-4 mx-auto px-8 relative"
>
<p className="md:text-2xl text-2xl font-medium text-center text-white relative z-20 max-w-2xl mx-auto">
With insomnia, nothing's real. Everything is far away. Everything
is a copy, of a copy, of a copy
</p>
<AnimatePresence>
{hovered && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="h-full w-full absolute inset-0"
>
<CanvasRevealEffect
animationSpeed={5}
containerClassName="bg-transparent"
colors={[
[59, 130, 246],
[139, 92, 246],
]}
opacities={[0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 1]}
dotSize={2}
/>
</motion.div>
)}
</AnimatePresence>
<div className="absolute inset-0 [mask-image:radial-gradient(400px_at_center,white,transparent)] bg-black/50 dark:bg-black/90" />
</div>
);
}
const Card = ({
title,
icon,
children,
}: {
title: string,
icon: React.ReactNode,
children?: React.ReactNode,
}) => {
const [hovered, setHovered] = React.useState(false);
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className="border border-black/[0.2] group/canvas-card flex items-center justify-center dark:border-white/[0.2] max-w-sm w-full mx-auto p-4 relative h-[30rem] relative"
>
<Icon className="absolute h-6 w-6 -top-3 -left-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -bottom-3 -left-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -top-3 -right-3 dark:text-white text-black" />
<Icon className="absolute h-6 w-6 -bottom-3 -right-3 dark:text-white text-black" />
<AnimatePresence>
{hovered && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="h-full w-full absolute inset-0"
>
{children}
</motion.div>
)}
</AnimatePresence>
<div className="relative z-20">
<div className="text-center group-hover/canvas-card:-translate-y-4 group-hover/canvas-card:opacity-0 transition duration-200 w-full mx-auto flex items-center justify-center">
{icon}
</div>
<h2 className="dark:text-white text-xl opacity-0 group-hover/canvas-card:opacity-100 relative z-10 text-black mt-4 font-bold group-hover/canvas-card:text-white group-hover/canvas-card:-translate-y-2 transition duration-200">
{title}
</h2>
</div>
</div>
);
};
const AceternityIcon = () => {
return (
<svg
width="66"
height="65"
viewBox="0 0 66 65"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-10 w-10 text-black dark:text-white group-hover/canvas-card:text-white "
>
<path
d="M8 8.05571C8 8.05571 54.9009 18.1782 57.8687 30.062C60.8365 41.9458 9.05432 57.4696 9.05432 57.4696"
stroke="currentColor"
strokeWidth="15"
strokeMiterlimit="3.86874"
strokeLinecap="round"
style={{ mixBlendMode: "darken" }}
/>
</svg>
);
};
const Icon = ({ className, ...rest }: any) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className={className}
{...rest}
>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 6v12m6-6H6" />
</svg>
);
};
export { DemoWithCards, SectionDemo, StaticDemo }