AnimBits
componentbuttons-liftsource: ok · refreshed
Lift Button
Button that lifts up on hover
npx shadcn add "https://animbits.dev/r/buttons-lift.json"free
No selection tags yet — empty means no evidence, not lack of support.
Dependencies
Bundle weight · mediumanimationmotion
Files2 · source cached 10/8/2026, 8:50:01 AM
registry/new-york/animations/buttons/lift.tsx
"use client";
import { motion, type HTMLMotionProps } from "motion/react";
import { useHoverLift } from "@/lib/use-hover-lift";
interface LiftButtonProps extends Omit<HTMLMotionProps<"button">, "animate"> {
children: React.ReactNode;
liftHeight?: number;
shadow?: boolean;
}
export function LiftButton({
children,
liftHeight = 8,
shadow = true,
...props
}: LiftButtonProps) {
const liftProps = useHoverLift({
liftDistance: liftHeight,
addShadow: shadow,
});
return (
<motion.button {...liftProps} {...props}>
{children}
</motion.button>
);
}
lib/use-hover-lift.ts
import { type MotionProps, type Easing } from "motion/react";
export interface UseHoverLiftOptions {
liftDistance?: number;
addShadow?: boolean;
shadowIntensity?: number;
duration?: number;
ease?: Easing | Easing[];
scale?: number;
}
export function useHoverLift(options: UseHoverLiftOptions = {}): MotionProps {
const {
liftDistance = 8,
addShadow = true,
shadowIntensity = 0.3,
duration = 0.2,
ease = "easeOut",
scale = 1,
} = options;
const shadowBlur = liftDistance * 2;
const shadowSpread = Math.round(liftDistance / 4);
return {
initial: {
y: 0,
scale: 1,
boxShadow: addShadow
? `0 2px 4px rgba(0, 0, 0, ${shadowIntensity * 0.3})`
: undefined,
},
whileHover: {
y: -liftDistance,
scale,
boxShadow: addShadow
? `0 ${shadowBlur}px ${shadowBlur + shadowSpread}px rgba(0, 0, 0, ${shadowIntensity})`
: undefined,
},
transition: {
duration,
ease,
},
};
}