Skip to main content

Custom Paths

Shape and Frame take a path generator that defines their silhouette. StageRoutine ships common shapes in paths, but you can pass your own when you need something else.

The PathFunction Contract​

A path generator is a pure function that returns an SVG path string (the d attribute):

import type { PathContext, PathFunction } from "stageroutine";

type PathFunction = (width: number, height: number, context?: PathContext) => string;

The optional context provides stroke metrics:

  • context.strokeWidth: outline stroke width in pixels (default: 0).
  • context.inset: inset from the container edge in pixels (default: 0).

Subtract half the stroke width so the outline stays inside the bounds:

const pad = (context?.strokeWidth ?? 0) / 2 + (context?.inset ?? 0);

A Custom Path​

A note with a folded corner. The second subpath draws the fold line:

import { type PathFunction, Shape } from "stageroutine";

const note: PathFunction = (w, h, ctx) => {
const p = (ctx?.strokeWidth ?? 0) / 2;
const f = Math.min(w, h) * 0.28;
return `M ${p} ${p} H ${w - p - f} L ${w - p} ${p + f} V ${h - p} H ${p} Z
M ${w - p - f} ${p} V ${p + f} H ${w - p}`;
};

const callout = Shape(note, "Custom path", {
position: [80, 45],
origin: "center",
width: 18.33,
height: 12.5,
borderColor: "#38bdf8",
strokeWidth: 2,
});

Shape masks its surface with the path, so the fill follows the silhouette automatically. Wind every subpath the same way to keep overlapping parts solid.

Built-in Paths​

Callout shapes such as paths.speechBubble() and paths.thoughtBubble() ship as path generators. See Shapes & Frames for the full catalog.

Custom Paths with Frame​

Frame clips media to any custom path. Reuse the note generator above:

import { Frame, Image } from "stageroutine";

const photo = Frame(note, Image("./hero.png", { fit: "cover" }), {
width: 21.67,
height: 15,
borderColor: "#38bdf8",
strokeWidth: 2,
});

Automatic Connector Tracking​

You do not need to write intersection math for custom paths.

StageRoutine's layout engine uses raycast bisection to find the exact perimeter point where connectors meet your shape boundary. Connectors attach cleanly to any custom closed SVG path contour.

API Reference​