Parallax Card
jarvis-ui/parallax-cardFreeComponent
A generic card with pointer-driven tilt, glare, and parallax motion.
Live preview
live · rendered by the registry
Rendered by jarvis-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.jarv.is/r/parallax-card.jsonSource
1"use client";23import {4 type HTMLMotionProps,5 motion,6 type MotionStyle,7 useMotionTemplate,8 useMotionValue,9 useSpring,10 useTransform,11} from "motion/react";12import * as React from "react";1314import { cn } from "@/lib/utils";1516type SpringConfig = {17 stiffness: number;18 damping: number;19 mass: number;20};2122type ParallaxCardProps = Omit<HTMLMotionProps<"div">, "children"> & {23 children: React.ReactNode;24 contentClassName?: string;25 contentStyle?: MotionStyle;26 glareClassName?: string;27 disabled?: boolean;28 maxTilt?: number;29 perspective?: number;30 scale?: number;31 glare?: boolean;32 glareMaxOpacity?: number;33 parallaxShift?: number;34 spring?: Partial<SpringConfig>;35};3637const defaultSpring = {38 stiffness: 300,39 damping: 30,40 mass: 0.5,41} satisfies SpringConfig;4243function ParallaxCard({44 children,45 className,46 contentClassName,47 contentStyle,48 glareClassName,49 disabled = false,50 maxTilt = 8,51 perspective = 800,52 scale: hoverScale = 1.02,53 glare = true,54 glareMaxOpacity = 0.16,55 parallaxShift = 6,56 spring,57 style,58 onMouseEnter,59 onMouseLeave,60 onMouseMove,61 ...props62}: ParallaxCardProps) {63 const cardRef = React.useRef<HTMLDivElement>(null);64 const rectRef = React.useRef<DOMRect | null>(null);65 const [prefersStaticCard, setPrefersStaticCard] = React.useState(false);66 const stiffness = spring?.stiffness ?? defaultSpring.stiffness;67 const damping = spring?.damping ?? defaultSpring.damping;68 const mass = spring?.mass ?? defaultSpring.mass;6970 React.useEffect(() => {71 const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");72 const finePointer = window.matchMedia("(pointer: fine)");73 const updatePreference = () => {74 setPrefersStaticCard(reducedMotion.matches || !finePointer.matches);75 };7677 updatePreference();78 reducedMotion.addEventListener("change", updatePreference);79 finePointer.addEventListener("change", updatePreference);8081 return () => {82 reducedMotion.removeEventListener("change", updatePreference);83 finePointer.removeEventListener("change", updatePreference);84 };85 }, []);8687 const springConfig = React.useMemo(88 () => ({ stiffness, damping, mass }),89 [stiffness, damping, mass],90 );91 const mouseX = useMotionValue(0.5);92 const mouseY = useMotionValue(0.5);93 const isHovered = useMotionValue(0);9495 const rawRotateY = useTransform(mouseX, [0, 1], [maxTilt, -maxTilt]);96 const rawRotateX = useTransform(mouseY, [0, 1], [-maxTilt, maxTilt]);97// … truncated
What it pulls in
npm packages
Files it writes
More from jarvis-ui
All 10 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Browser Windowbrowser-window | jarvis-ui | Components | Free | no deps | |
| Cookie Consentcookie-consent | jarvis-ui | Components | Free | no deps | |
| Copy Buttoncopy-button | jarvis-ui | Components | Free | 1 dep | |
| Copyable Fieldcopyable-field | jarvis-ui | Components | Free | no deps | |
| Scroll Areascroll-area | jarvis-ui | Components | Free | 1 dep | |
| Stepperstepper | jarvis-ui | Components | Free | 1 dep | |
| Tipovertipover | jarvis-ui | Components | Free | 1 dep · 2 files | |
| Toasttoast | jarvis-ui | Components | Free | 2 deps |
