Component

Funnel Chart

A vertical conversion funnel: one bar per step, filled to its share of the first step, with the continue-rate and drop-off between each pair of steps. It renders an ordered list, so every figure is real text.

Basic

Steps with optional descriptions.

  1. VisitorsLanded on the site
    12,400100.0% of top
    25.0% continue−9,300 dropped
  2. Sign-upsCreated an account
    3,10025.0% of top
    38.1% continue−1,920 dropped
  3. TrialsStarted a free trial
    1,1809.5% of top
    35.6% continue−760 dropped
  4. Purchases
    4203.4% of top

Custom copy and formatting

Every label and number format is a prop, for localisation.

  1. VisitorsLanded on the site
    12,400100% of visitors
    25% moved on9,300 left
  2. Sign-upsCreated an account
    3,10025% of visitors
    38% moved on1,920 left
  3. TrialsStarted a free trial
    1,18010% of visitors
    36% moved on760 left
  4. Purchases
    4203% of visitors

Installation

$pnpm add @refraction-ui/react

Usage

tsx
import { FunnelChart } from '@refraction-ui/react'

export function CheckoutFunnel() {
  return (
    <FunnelChart
      aria-label="Checkout funnel"
      steps={[
        { id: 'visit', label: 'Visitors', value: 12400 },
        { id: 'signup', label: 'Sign-ups', value: 3100 },
        { id: 'buy', label: 'Purchases', value: 420 },
      ]}
    />
  )
}

Props

PropTypeDefaultDescription
steps{ id: string; label: string; description?: string; value: number }[]--The funnel steps, top first.
formatValue(value: number) => stringtoLocaleStringFormats counts.
formatPercent(percent: number) => string'25.0%'Formats a 0–100 percent.
minBarPercentnumber6Smallest bar width in percent, so tiny steps stay visible.
shareLabel(share: string) => string'… of top'Copy for a step's share of the top step.
conversionLabel(percent: string) => string'… continue'Copy for the continue-rate between steps.
droppedLabel(count: string) => string'−… dropped'Copy for the count lost between steps.
classNamestring--Merged onto the root <ol>.