React Component for Drawing Arrows Between Elements – CurvedArrow

Description:

CurvedArrow is a DOM-aware React component that renders animated, curved SVG arrows.

It connects two elements or coordinates with support for various curve styles, custom arrowheads, and gradient strokes.

Features

  • 🎯 Flexible Positioning: Connect arrows using either element references or specific XY coordinates.
  • 🌈 Customizable Curves: Choose from multiple curve styles, including smooth, s-curve, wave, and zigzag.
  • 🧭 Obstacle Avoidance: Automatically reroutes arrows to avoid designated elements on the screen.
  • 🖋️ Stylable Arrowheads: Customize arrowhead shapes, colors, fills, and sizes for both ends of the arrow.
  • 🧩 Two-Layer Rendering: Manages z-index with UNDER and OVER layers for correct stacking with other UI elements.
  • 💫 Built-in Animations: Apply an optional motion dash overlay with configurable duration and direction.
  • ⚙️ Performance Optimized: Utilizes ResizeObserver, MutationObserver, and requestAnimationFrame for efficient updates.
  • Accessibility Ready: Implements ARIA labels and roles to ensure the component is accessible.
  • 🎨 Tailwind Integration: Leverages class-variance-authority for easy styling with variants like glow, neon, and fire.

Use Cases

  • Diagram tools: Create flowchart and architecture diagram applications with connecting arrows.
  • Tutorial systems: Guide users through interface elements with animated pointer arrows.
  • Interactive UIs: Visualize relationships between components in data visualization dashboards.
  • Educational content: Build interactive learning materials with connected concept maps.

How to Use It

1. Install CurvedArrow into your project with shadcn/ui CLI.

For npm:

npx shadcn@canary add https://dsa.hncore.website/r/curved-arrow.json

For bun:

bunx --bun shadcn@canary add https://dsa.hncore.website/r/curved-arrow.json

For pnpm:

pnpx shadcn@canary add https://dsa.hncore.website/r/curved-arrow.json

2. Import the component into your React file.

import { CurvedArrow } from "@/components/curved-arrow";

3. Connecting two DOM elements. Create ref objects using the useRef hook and assign them to the elements you want to connect. The parent container must have a relative position for the arrow to be placed correctly.

import { CurvedArrow } from "./CurvedArrow";
import { useRef } from "react";
function ElementConnector() {
  const startRef = useRef(null);
  const endRef = useRef(null);
  return (
    <div className="relative h-96 w-full border p-4">
      <div ref={startRef} className="absolute top-10 left-10 z-10 w-24 h-24 bg-gray-200 flex items-center justify-center">
        Start
      </div>
      <div ref={endRef} className="absolute bottom-10 right-10 z-10 w-24 h-24 bg-gray-200 flex items-center justify-center">
        End
      </div>
      <CurvedArrow
        startElement={startRef}
        endElement={endRef}
        curveType="s-curve"
        variant="neon"
      />
    </div>
  );
}

4. You can also draw an arrow between specific coordinates without attaching it to elements. Use the startX, startY, endX, and endY props to define the points. This method is useful for static diagrams or when element refs are not available.

function CoordinateConnector() {
  return (
    <div className="relative h-96 w-full border p-4">
      <CurvedArrow
        startX={50}
        startY={50}
        endX={300}
        endY={200}
        curveType="wave"
        color="#3498db"
        strokeWidth={5}
        endArrowShape="circle"
        endArrowFilled={true}
      />
    </div>
  );
}

5. All component props.

PropTypeDefaultDescription
startElementReact.RefObject<HTMLElement>Reference to the start element. Overrides startX/startY.
endElementReact.RefObject<HTMLElement>Reference to the end element. Overrides endX/endY.
obstacleElementsReact.RefObject<HTMLElement>[][]Array of refs to elements for the arrow to avoid.
startX, startYnumber0Absolute start coordinates if startElement is not provided.
endX, endYnumber100Absolute end coordinates if endElement is not provided.
startPositionstring"center"Docking position for startElement (e.g., top, right-center).
endPositionstring"center"Docking position for endElement.
curveIntensitynumber0.4Curve strength (0 to 1+).
curveTypestring"smooth"Curve style (smooth, dramatic, s-curve, wave, zigzag).
curveDirection"up" | "down" | "left" | "right" | "auto""auto"Directional bias for curves.
strokeWidthnumber4Base stroke width for the main path.
colorstring"#852DEE"Solid stroke color.
gradientFromstring"#ffffff"Gradient start color.
gradientTostring"#852DEE"Gradient end color.
showStartArrowbooleanfalseShows an arrowhead at the start.
showEndArrowbooleantrueShows an arrowhead at the end.
startArrowShapestring"triangle"Shape of the start arrowhead (circle, star, chevron).
endArrowShapestring"triangle"Shape of the end arrowhead.
startArrowRotationnumber0Rotation for the start arrowhead in degrees.
endArrowRotationnumber0Rotation for the end arrowhead in degrees.
startArrowSizenumberSize override for the start arrowhead.
endArrowSizenumberSize override for the end arrowhead.
arrowSizenumber20Base size for arrowheads.
startArrowFilledbooleanfalseFills the start arrowhead with stroke or gradient color.
endArrowFilledbooleanfalseFills the end arrowhead with stroke or gradient color.
startArrowStrokeColorstringStroke color override for the start arrowhead.
endArrowStrokeColorstringStroke color override for the end arrowhead.
startArrowFillColorstringFill color override for the start arrowhead.
endArrowFillColorstringFill color override for the end arrowhead.
startArrowStrokeWidthnumberStroke width override for the start arrowhead.
endArrowStrokeWidthnumberStroke width override for the end arrowhead.
startArrowOpacitynumber1Opacity for the start arrowhead (0 to 1).
endArrowOpacitynumber1Opacity for the end arrowhead (0 to 1).
startHeadLayer"under" | "over""over"Layer for the start arrowhead.
endHeadLayer"under" | "over""over"Layer for the end arrowhead.
startLineOverHeadbooleanfalseDraws a line overlay over the start arrowhead.
endLineOverHeadbooleanfalseDraws a line overlay over the end arrowhead.
animatedbooleantrueEnables the animated dash overlay.
animationDurationstring"2s"Duration of one animation cycle.
animationDelaystring"0s"Delay before the animation starts.
animationDirection"forward" | "reverse" | "alternate" | "alternate-reverse""forward"Animation direction mode.
ariaLabelstring"Curved arrow connector"Accessible label for the UNDER layer.
variantstring"default"Tailwind style variant (glow, neon, fire).
sizestring"default"Stroke size variant (xs, sm, lg).
classNamestringAdditional class names for the container.

FAQs

Q: Does CurvedArrow work with dynamically positioned elements?
A: Yes, the component tracks element position changes using ResizeObserver and MutationObserver.

Q: How does obstacle avoidance work?
A: The component uses heuristic routing algorithms to calculate paths around specified obstacle elements.

Q: Is the component accessible to screen readers?
A: Yes, it includes ARIA labels and proper semantic structure for accessibility compliance.

Add Comment