Components
Loading preview...
A wobbly svg line with a spring cursor interaction. This component is made with a simple svg quadratic curve, with 2+1 points. The start and end points of the curve positioned at the two edges of the parent container, either horizontally or vertically, depending on the isVertical prop. This means, the line will always be centered in the container, and it will always fill up the entire container, so make sure to position your container properly. The third point of the line is the control point, named Q, which is positioned at the center of the container by default. When the cursor moves close to the line (within grabThreshold), the control point will be controlled by the cursor's position. When the distance between them is greater than the releaseThreshold prop, the control point is animated back to the center of the container, with the help of motion's animate function. For better readability — the calculation of the control point's position, and the signal it's grabbed — done in a separate hook, called useElasticLineEvents. To achiave the elastic effect we use a springy transition by default, but feel free to experiment with other type of animations, easings, durations, etc. The compoment also have an animateInTransition prop, which is used when the line is initially rendered. If you want to skip this, just set the transiton's duration to 0.
@danielpetho
npx shadcn@latest add https://21st.dev/r/danielpetho/elastic-lineimport { motion } from "framer-motion"
import { ElasticLine } from "@/components/ui/elastic-line"
function Preview() {
const textVariants = {
hidden: { opacity: 0, y: 10 },
visible: (i: number) => ({
opacity: 1,
y: 0,
transition: {
delay: i * 0.3,
type: "spring",
stiffness: 300,
damping: 30,
},
}),
}
return (
<div className="w-full h-full flex flex-row items-center justify-center font-overusedGrotesk overflow-hidden to-white">
<div className="absolute left-0 top-0 w-full h-full px-6 sm:px-8 md:px-12 z-10">
{/* Animated elastic line */}
<ElasticLine
releaseThreshold={50}
strokeWidth={1}
animateInTransition={{
type: "spring",
stiffness: 300,
damping: 30,
delay: 0.15,
}}
/>
</div>
{/* This is just fluff for the demo */}
<div className="h-full flex flex-col py-6 w-full px-6 sm:px-8 md:px-12 font-light">
<div className="h-1/2 py-8 w-full items-end flex">
<motion.p
variants={textVariants}
initial="hidden"
animate="visible"
className="uppercase text-4xl sm:text-5xl md:text-6xl font-medium"
custom={0}
>
FANCY COMPONENTS
</motion.p>
</div>
<div className="flex flex-row pt-8 justify-between items-start gap-x-4">
<motion.p
variants={textVariants}
initial="hidden"
animate="visible"
className="w-1/3 uppercase md:text-7xl hidden md:block text-orange-500"
custom={0}
>
✽
</motion.p>
<motion.p
variants={textVariants}
initial="hidden"
animate="visible"
className="w-full md:w-2/3 sm:text-left text-base sm:text-xl md:text-2xl"
custom={1}
>
Ready to use, fancy, animated React components & microinteractions
for creative developers.
</motion.p>
</div>
{/* <div className="h-1/3 flex items-center justify-end">
<motion.p
variants={textVariants}
initial="hidden"
animate="visible"
custom={2}
>
</motion.p>
</div> */}
</div>
</div>
)
}
export { Preview }