Line Draw SVG Animation for React

SVG path that draws itself on scroll, hover, or mount. Presets: diamond, circle, star, heart, arrow.

Component

Scroll to animate (diamond)

Installation

 

Usage

Import

Add the LineDrawSvg import.

import { LineDrawSvg } from "@/components/line-draw-svg";

Use

Use with preset and trigger.

<LineDrawSvg preset="diamond" trigger="scroll" />;

Guidelines

  • Use trigger='scroll' for scroll-triggered reveals (e.g. in long pages).
  • Use trigger='hover' for interactive icons.
  • Use trigger='mount' for immediate draw on page load.
  • Presets: diamond, circle, star, heart, arrow.
  • ease: power1.inOut, power2.inOut, elastic.out, back.out, etc.

Props

All props are optional unless marked required. Use these to customize every aspect of the component.

PropTypeDefaultDescription
pathstring-Custom SVG path (d attribute). Overrides preset.
presetstring"diamond"Preset shape: "diamond", "circle", "star", "heart", "arrow".
trigger"scroll" | "hover" | "mount""scroll"When to draw: "scroll", "hover", or "mount".
durationnumber1Animation duration in seconds.
easestring"power2.inOut"GSAP ease: power1.inOut, power2.inOut, elastic.out, back.out, etc.
scrubboolean | number1ScrollTrigger scrub (true = smooth, number = seconds).
startstring"top 80%"ScrollTrigger start.
endstring"top 20%"ScrollTrigger end.
widthnumber120SVG width in pixels.
heightnumber120SVG height in pixels.
strokeWidthnumber2Stroke width in pixels.
strokeClassNamestring-Classes for the path stroke (e.g. text-amber-500).

Accessibility

  • Decorative visual effect: the svg is marked aria-hidden true so screen readers skip it, and there are no focusable or operable controls.
  • The hover trigger uses onMouseEnter and onMouseLeave only, so it is pointer-only and cannot be activated or reversed via the keyboard.
  • No element receives focus, so there is no focus ring or focus management to consider for this component.
  • It does not check prefers-reduced-motion, so the draw animation runs unconditionally; it should be guarded with a matchMedia reduced-motion query to instantly show or hide the path for users who prefer reduced motion.

Performance

  • Animation is driven entirely by the SVG strokeDashoffset property, which is paint-efficient for a thin single-path outline but is not a GPU-compositor-only transform like transform or opacity.
  • GSAP and ScrollTrigger schedule updates on a shared requestAnimationFrame loop rather than per-tween timers, keeping the scroll-scrubbed draw smooth.
  • Scroll mode wraps its tween in gsap.context and returns ctx.revert on cleanup, which kills the tween and removes the ScrollTrigger to prevent leaks on unmount.
  • Path length is measured once via getTotalLength in useLayoutEffect to avoid layout thrash; the hover effect re-reads it per toggle, which is cheap for these small fixed presets.
  • There is no IntersectionObserver, will-change hint, or visibility gating, and mount and hover tweens have no explicit kill on unmount, so rapid mounting of many instances relies on GSAP and element teardown for cleanup.

Examples

Scroll (diamond)

Diamond draws on scroll into view.

Scroll to animate (diamond)

import { LineDrawSvg } from "@/components/line-draw-svg";

<LineDrawSvg preset="diamond" trigger="scroll" />;

Hover (star)

Star draws when user hovers.

Hover to animate (star)

import { LineDrawSvg } from "@/components/line-draw-svg";

<LineDrawSvg preset="star" trigger="hover" />;

Mount (circle)

Circle draws immediately on mount.

Animates on mount (circle)

import { LineDrawSvg } from "@/components/line-draw-svg";

<LineDrawSvg preset="circle" trigger="mount" />;

Size & easing

Larger size, thicker stroke, elastic easing.

Scroll to animate (diamond)

import { LineDrawSvg } from "@/components/line-draw-svg";

<LineDrawSvg
  preset="heart"
  duration={1.5}
  ease="elastic.out"
  width={160}
  height={160}
  strokeWidth={3}
/>;

Custom path

Custom SVG path and stroke color.

Scroll to animate (diamond)

import { LineDrawSvg } from "@/components/line-draw-svg";

<LineDrawSvg
  path="M10 50 L90 50"
  trigger="mount"
  strokeClassName="text-amber-500"
/>;

Last updated on Jun 19

Made with ❤️ by Pulkit &

© 2026 Pulkit. All rights reserved

Last updated: