Components
Loading preview...
@danielpetho
npx shadcn@latest add https://21st.dev/r/danielpetho/use-elastic-line-events'use client'
import { useRef } from "react"
import { motion } from "framer-motion"
import { useElasticLineEvents } from "@/components/hooks/use-elastic-line-events"
function ElasticLineDemo() {
const verticalRef = useRef<SVGSVGElement>(null)
const horizontalRef = useRef<SVGSVGElement>(null)
const vertical = useElasticLineEvents(verticalRef, true, 20, 100)
const horizontal = useElasticLineEvents(horizontalRef, false, 20, 100)
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 p-8 max-w-4xl mx-auto">
{/* Vertical Line Demo */}
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-medium">Vertical Elastic Line</h3>
<p className="text-sm text-muted-foreground">
Move your cursor near the center line
</p>
</div>
<div className="relative aspect-square w-full border rounded-lg bg-muted/30">
<svg
ref={verticalRef}
className="w-full h-full"
viewBox="0 0 400 400"
style={{ touchAction: "none" }}
>
<path
d={`M 200,0 Q ${vertical.controlPoint.x},${vertical.controlPoint.y} 200,400`}
stroke={vertical.isGrabbed ? "#3b82f6" : "#94a3b8"}
strokeWidth="2"
fill="none"
/>
</svg>
</div>
</div>
{/* Horizontal Line Demo */}
<div className="space-y-4">
<div className="space-y-2">
<h3 className="text-lg font-medium">Horizontal Elastic Line</h3>
<p className="text-sm text-muted-foreground">
Move your cursor near the center line
</p>
</div>
<div className="relative aspect-square w-full border rounded-lg bg-muted/30">
<svg
ref={horizontalRef}
className="w-full h-full"
viewBox="0 0 400 400"
style={{ touchAction: "none" }}
>
<path
d={`M 0,200 Q ${horizontal.controlPoint.x},${horizontal.controlPoint.y} 400,200`}
stroke={horizontal.isGrabbed ? "#3b82f6" : "#94a3b8"}
strokeWidth="2"
fill="none"
/>
</svg>
</div>
</div>
{/* Documentation */}
<div className="md:col-span-2">
<div className="space-y-4 p-6 border rounded-lg">
<h3 className="text-lg font-medium">About useElasticLineEvents</h3>
<div className="space-y-4">
<pre className="bg-muted p-4 rounded-md text-xs overflow-x-auto">
{`const { isGrabbed, controlPoint } = useElasticLineEvents(
svgRef, // SVG element ref
isVertical, // boolean
grabThreshold, // number (px)
releaseThreshold // number (px)
)`}
</pre>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
<div>
<h4 className="font-medium mb-2">Features</h4>
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
<li>Mouse position tracking</li>
<li>Automatic grab/release</li>
<li>Responsive control points</li>
<li>Vertical/horizontal modes</li>
</ul>
</div>
<div>
<h4 className="font-medium mb-2">Use Cases</h4>
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
<li>Interactive dividers</li>
<li>Navigation indicators</li>
<li>Playful UI elements</li>
<li>Custom cursors</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export { ElasticLineDemo }