Funnel

Conversion funnel — vertical stack of trapezoidal stages whose width is proportional to each stage's value. Pure SVG; no heavy peer dep.

Installation

pnpm
pnpm dlx @hex-core/cli add funnel

Usage

tsx
import { Funnel } from "@/components/ui/funnel"

Signup funnel

Standard top-of-funnel → conversion drop-off.

tsx
<Funnel stages={[
  { id: "visit", label: "Visited", value: 10000 },
  { id: "signup", label: "Signed up", value: 1200 },
  { id: "active", label: "Active", value: 480 },
  { id: "paid", label: "Paid", value: 95 },
]} />

Click stages to drill in

Wire onStageClick to a route or modal for stage detail.

tsx
<Funnel stages={data} onStageClick={(s) => router.push(`/stages/${s.id}`)} />

API Reference

PropTypeDefaultDescription
stagesrequired
objectOrdered top-to-bottom array of { id, label, value }. Values must be non-negative.
width
number480SVG pixel width.
height
number360SVG pixel height.
gap
number4Pixel gap between stages.
showConversion
booleantrueShow stage-to-stage conversion percentages alongside the funnel.
onStageClick
functionCalled with the clicked FunnelStage.
className
stringAdditional CSS classes on the SVG element.

AI Guidance

When to use

Visualize linear conversion drop-off — onboarding step completion, marketing-funnel rates, sales pipeline stages, ETL row counts. Use when each stage is a strict subset of the previous and the magnitude of the drop is the message.

When not to use

Don't use for non-monotonic data where a later stage can exceed an earlier one (use a column chart). Don't use for branching funnels where flow splits across paths (use Sankey). Don't use for ranked categorical data without a flow concept (use Pyramid).

Common mistakes

  • Stage values that aren't monotonically non-increasing — visually misleads users into thinking the funnel "recovers". Validate upstream
  • Negative values — produce zero-width stages or NaN positions. Filter or clamp upstream
  • More than ~8 stages — labels become unreadable. Group adjacent stages or use Sankey

Accessibility

The SVG carries role="img" with a <title> and <desc> summarizing stage count and peak value. For agent outputs, also expose a parallel <table> of label/value/conversion-rate triples so screen-reader users get the magnitudes.

Token budget: 280

Verified against @hex-core/components@1.12.0