Method skeleton
- 01Choose one visual protagonist
- 02Specify scroll or interaction triggers
- 03Limit first-load assets and mobile fallback
Loading…
Skill · Creator method
A recurring 3d and motion hero method derived from 11 published cases by Aceternity UI.
Method skeleton
Creator evidence
Case evidence

// components/ui/parallax-hero-images.tsx "use client"; import React, { useEffect, useState, useMemo, useCallback, memo } from "react"; import { motion, useMotionValue, useSpring, useTransform, MotionValue, } from "motion/react"; import { cn } from "@/lib/utils"; type ImagePosition = { src: string; position: | "top-left" | "top-right" | "mid-left" | "mid-right" | "bottom-left" | "bottom-right" | "far-left" | "far-right"; depth: number; delay: number; }; const positionStyles: Record< ImagePosition["position"], { top: string; left?: string; right?: string } > = { "top-left": { top: "8%", left: "4%" }, "top-right": { top: "8%", right: "4%" }, "mid-left": { top: "38%", left: "6%" }, "mid-right": { top: "38%", right: "6%" }, "bottom-left": { top: "68%", left: "4%" }, "bottom-right": { top: "68%", right: "4%" }, "far-left": { top: "52%", left: "2%" }, "far-right": { top: "52%", right: "2%" },…
Prompt
// components/ui/parallax-hero-images.tsx "use client"; import React, { useEffect, useState, useMemo, useCallback, memo } from "react"; import { motion, useMotionValue, useSpring, useTransform, MotionValue, } from "motion/react"; import { …
// components/ui/3d-pin.tsx "use client"; import React, { useState } from "react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const PinContainer = ({ children, title, href, className, containerClassName, }: { children: React.ReactNode; title?: string; href?: string; className?: string; containerClassName?: string; }) => { const [transform, setTransform] = useState( "translate(-50%,-50%) rotateX(0deg)" ); const onMouseEnter = () => { setTransform("translate(-50%,-50%) rotateX(40deg) scale(0.8)"); }; const onMouseLeave = () => { setTransform("translate(-50%,-50%) rotateX(0deg) scale(1)"); }; return ( <a className={cn( "relative group/pin z-50 cursor-pointer", containerClassName )} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} href={href || "/"} > <div style={{ perspective: "1000px", transform: "rotateX(70deg) translateZ(0deg)", }} className="…
Prompt
// components/ui/3d-pin.tsx "use client"; import React, { useState } from "react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const PinContainer = ({ children, title, href, className, containerClassName…

// components/ui/3d-globe.tsx "use client"; import React, { useRef, useMemo, useState, useCallback, Suspense } from "react"; import { Canvas, useFrame, useThree } from "@react-three/fiber"; import { OrbitControls, Html, useTexture } from "@react-three/drei"; import * as THREE from "three"; import { cn } from "@/lib/utils"; // ============================================================================ // Types // ============================================================================ export interface GlobeMarker { lat: number; lng: number; src: string; label?: string; size?: number; } export interface Globe3DConfig { /** Globe radius */ radius?: number; /** Globe base color (used as fallback or tint) */ globeColor?: string; /** URL to the Earth texture map */ textureUrl?: string; /** URL to the bump/elevation map for terrain */ bumpMapUrl?: string; /** Whether to show atmosphere gl…
Prompt
// components/ui/3d-globe.tsx "use client"; import React, { useRef, useMemo, useState, useCallback, Suspense } from "react"; import { Canvas, useFrame, useThree } from "@react-three/fiber"; import { OrbitControls, Html, useTexture } from "…

// components/ui/macbook-scroll.tsx "use client"; import React, { useEffect, useMemo, useRef, useState } from "react"; import { MotionValue, motion, useScroll, useTransform } from "motion/react"; import { cn } from "@/lib/utils"; import { IconBrightnessDown, IconBrightnessUp, IconCaretRightFilled, IconCaretUpFilled, IconChevronUp, IconMicrophone, IconMoon, IconPlayerSkipForward, IconPlayerTrackNext, IconPlayerTrackPrev, IconTable, IconVolume, IconVolume2, IconVolume3, } from "@tabler/icons-react"; import { IconSearch } from "@tabler/icons-react"; import { IconWorld } from "@tabler/icons-react"; import { IconCommand } from "@tabler/icons-react"; import { IconCaretLeftFilled } from "@tabler/icons-react"; import { IconCaretDownFilled } from "@tabler/icons-react"; export const MacbookScroll = ({ src, showGradient, title, badge, }: { src?: string; showGradient?: boolean; title?: string | Rea…
Prompt
// components/ui/macbook-scroll.tsx "use client"; import React, { useEffect, useMemo, useRef, useState } from "react"; import { MotionValue, motion, useScroll, useTransform } from "motion/react"; import { cn } from "@/lib/utils"; import { …
// components/ui/container-scroll-animation.tsx "use client"; import React, { useRef } from "react"; import { useScroll, useTransform, motion, MotionValue } from "motion/react"; export const ContainerScroll = ({ titleComponent, children, }: { titleComponent: string | React.ReactNode; children: React.ReactNode; }) => { const containerRef = useRef<HTMLDivElement>(null); const { scrollYProgress } = useScroll({ target: containerRef, }); const [isMobile, setIsMobile] = React.useState(false); React.useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth <= 768); }; checkMobile(); window.addEventListener("resize", checkMobile); return () => { window.removeEventListener("resize", checkMobile); }; }, []); const scaleDimensions = () => { return isMobile ? [0.7, 0.9] : [1.05, 1]; }; const rotate = useTransform(scrollYProgress, [0, 1], [20, 0]); const scale = useTransform(scroll…
Prompt
// components/ui/container-scroll-animation.tsx "use client"; import React, { useRef } from "react"; import { useScroll, useTransform, motion, MotionValue } from "motion/react"; export const ContainerScroll = ({ titleComponent, children, }…
// components/ui/background-gradient-animation.tsx "use client"; import { cn } from "@/lib/utils"; import { useEffect, useRef, useState } from "react"; export const BackgroundGradientAnimation = ({ gradientBackgroundStart = "rgb(108, 0, 162)", gradientBackgroundEnd = "rgb(0, 17, 82)", firstColor = "18, 113, 255", secondColor = "221, 74, 255", thirdColor = "100, 220, 255", fourthColor = "200, 50, 50", fifthColor = "180, 180, 50", pointerColor = "140, 100, 255", size = "80%", blendingValue = "hard-light", children, className, interactive = true, containerClassName, }: { gradientBackgroundStart?: string; gradientBackgroundEnd?: string; firstColor?: string; secondColor?: string; thirdColor?: string; fourthColor?: string; fifthColor?: string; pointerColor?: string; size?: string; blendingValue?: string; children?: React.ReactNode; className?: string; interactive?: boolean; containerClassName…
Prompt
// components/ui/background-gradient-animation.tsx "use client"; import { cn } from "@/lib/utils"; import { useEffect, useRef, useState } from "react"; export const BackgroundGradientAnimation = ({ gradientBackgroundStart = "rgb(108, 0, 16…

// components/ui/hero-highlight.tsx "use client"; import { cn } from "@/lib/utils"; import { useMotionValue, motion, useMotionTemplate } from "motion/react"; import React from "react"; export const HeroHighlight = ({ children, className, containerClassName, }: { children: React.ReactNode; className?: string; containerClassName?: string; }) => { let mouseX = useMotionValue(0); let mouseY = useMotionValue(0); // SVG patterns for different states and themes const dotPatterns = { light: { default: `url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='16' height='16' fill='none'%3E%3Ccircle fill='%23d4d4d4' id='pattern-circle' cx='10' cy='10' r='2.5'%3E%3C/circle%3E%3C/svg%3E")`, hover: `url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='16' height='16' fill='none'%3E%3Ccircle fill='…
Prompt
// components/ui/hero-highlight.tsx "use client"; import { cn } from "@/lib/utils"; import { useMotionValue, motion, useMotionTemplate } from "motion/react"; import React from "react"; export const HeroHighlight = ({ children, className, c…

// components/ui/hero-parallax.tsx "use client"; import React from "react"; import { motion, useScroll, useTransform, useSpring, MotionValue, } from "motion/react"; export const HeroParallax = ({ products, }: { products: { title: string; link: string; thumbnail: string; }[]; }) => { const firstRow = products.slice(0, 5); const secondRow = products.slice(5, 10); const thirdRow = products.slice(10, 15); const ref = React.useRef(null); const { scrollYProgress } = useScroll({ target: ref, offset: ["start start", "end start"], }); const springConfig = { stiffness: 300, damping: 30, bounce: 100 }; const translateX = useSpring( useTransform(scrollYProgress, [0, 1], [0, 1000]), springConfig ); const translateXReverse = useSpring( useTransform(scrollYProgress, [0, 1], [0, -1000]), springConfig ); const rotateX = useSpring( useTransform(scrollYProgress, [0, 0.2], [15, 0]), springConfig ); const o…
Prompt
// components/ui/hero-parallax.tsx "use client"; import React from "react"; import { motion, useScroll, useTransform, useSpring, MotionValue, } from "motion/react"; export const HeroParallax = ({ products, }: { products: { title: string; l…
// components/ui/parallax-scroll.tsx "use client"; import { useScroll, useTransform } from "motion/react"; import { useRef } from "react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const ParallaxScroll = ({ images, className, }: { images: string[]; className?: string; }) => { const gridRef = useRef<any>(null); const { scrollYProgress } = useScroll({ container: gridRef, // remove this if your container is not fixed height offset: ["start start", "end start"], // remove this if your container is not fixed height }); const translateFirst = useTransform(scrollYProgress, [0, 1], [0, -200]); const translateSecond = useTransform(scrollYProgress, [0, 1], [0, 200]); const translateThird = useTransform(scrollYProgress, [0, 1], [0, -200]); const third = Math.ceil(images.length / 3); const firstPart = images.slice(0, third); const secondPart = images.slice(thir…
Prompt
// components/ui/parallax-scroll.tsx "use client"; import { useScroll, useTransform } from "motion/react"; import { useRef } from "react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const ParallaxScroll…

// components/ui/sticky-scroll-reveal.tsx "use client"; import React, { useEffect, useRef, useState } from "react"; import { useMotionValueEvent, useScroll } from "motion/react"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const StickyScroll = ({ content, contentClassName, }: { content: { title: string; description: string; content?: React.ReactNode | any; }[]; contentClassName?: string; }) => { const [activeCard, setActiveCard] = React.useState(0); const ref = useRef<any>(null); const { scrollYProgress } = useScroll({ // uncomment line 22 and comment line 23 if you DONT want the overflow container and want to have it change on the entire page scroll // target: ref container: ref, offset: ["start start", "end start"], }); const cardLength = content.length; useMotionValueEvent(scrollYProgress, "change", (latest) => { const cardsBreakpoints = content.ma…
Prompt
// components/ui/sticky-scroll-reveal.tsx "use client"; import React, { useEffect, useRef, useState } from "react"; import { useMotionValueEvent, useScroll } from "motion/react"; import { motion } from "motion/react"; import { cn } from "@…

// components/ui/3d-marquee.tsx "use client"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const ThreeDMarquee = ({ images, className, }: { images: string[]; className?: string; }) => { // Split the images array into 4 equal parts const chunkSize = Math.ceil(images.length / 4); const chunks = Array.from({ length: 4 }, (_, colIndex) => { const start = colIndex * chunkSize; return images.slice(start, start + chunkSize); }); return ( <div className={cn( "mx-auto block h-[600px] overflow-hidden rounded-2xl max-sm:h-100", className, )} > <div className="flex size-full items-center justify-center"> <div className="size-[1720px] shrink-0 scale-50 sm:scale-75 lg:scale-100"> <div style={{ transform: "rotateX(55deg) rotateY(0deg) rotateZ(-45deg)", }} className="relative top-96 right-[50%] grid size-full origin-top-left grid-cols-4 gap-8 transform-3d" > {chunks.m…
Prompt
// components/ui/3d-marquee.tsx "use client"; import { motion } from "motion/react"; import { cn } from "@/lib/utils"; export const ThreeDMarquee = ({ images, className, }: { images: string[]; className?: string; }) => { // Split the image…