Skip to content
quartiledocsv0.1
GitHub

Funnel

PreviewSVGReads selection

Shows how many reach each step of a process and the conversion from one step to the next.

Playground

Checkout funnel
Sep 7 – Oct 6, 2026

5 steps from Sessions (586,098) to Purchased (18,259), 3.12% overall. Product views 57.0% from previous; Added to cart 18.0% from previous; Checkout 49.1% from previous; Purchased 61.7% from previous.

Checkout funnel
StepValueFrom previous stepOf first step
Sessions586,098—100.0%
Product views334,07657.0%57.0%
Added to cart60,25618.0%10.3%
Checkout29,58049.1%5.0%
Purchased18,25961.7%3.1%
align
<Funnel
  data={funnel}
  step="step"
  value="value"
/>

Installation

Funnel is exported from @quartile/react, alongside every other chart and component.

git clone https://github.com/zinnoberHaus/quartile

Not on npm yet: build the package from the clone as described in Installation. The preview API may change before publication.

Usage

One row per step, in order. Raw rows work too: values that share a step are summed, and steps keep the order they first appear in.

import { Funnel } from '@quartile/react';

const steps = [
  { step: 'Sessions', value: 586098 },
  { step: 'Added to cart', value: 60256 },
  { step: 'Purchased', value: 18259 },
];

export function Checkout() {
  return <Funnel data={steps} step="step" value="value" aria-label="Checkout funnel" />;
}
Funnel reads the nearest <Selection> and does not publish to it. Pass selection={false} to show the unfiltered funnel. See Linked selections.

Props

PropTypeDefaultDescription
datarequiredDataInput<R>—One row per step in funnel order, or raw rows (values sharing a step are summed).
steprequiredkeyof R & string—Field naming the step. Steps keep the order they first appear in.
valuerequiredkeyof R & string—Field with the count that reached the step.
formatFormatter—Formats counts. Defaults to integers for plain rows (a field named value would otherwise be inferred as currency); a dataset's declared format is used as given.
align'start' | 'center''start'start: label and figures on one line, a bar under them with the previous step as a ghost. center: tapering bars centered on one axis, figures under each bar.
overallbooleantrueShows the first-to-last conversion under the steps. Defaults to true.
selectionstring | false—Selection to read from. Defaults to the nearest; false opts out.
Frame and state props shared with the charts (11) · ChartBaseProps, ChartStateProps
PropTypeDefaultDescription
heightnumber—Plot height in px. Width always fills the container.
classNamestring——
styleCSSProperties——
aria-labelstring—Accessible name. A summary of the data is generated and rendered as hidden text inside the figure.
view'chart' | 'table'—table renders the same data as a table, with the same formats, at the chart's size. Large lazy tables expose a data-view control rather than mounting every hidden row.
tooltipNotestring—Plain-text context shown with tooltips and included in the accessible chart description.
loadingboolean | string—Shows the loading state at the chart's size, so the layout never jumps.
errorboolean | string | Error | null—Shows the error state. A string or Error becomes the message.
errorCodestring—Shown in the error state; copyable for support.
onRetry() => void——
empty{ title?: string; description?: string; action?: ReactNode }—Title and description for the empty state. Shown when there are no rows.

Accessibility

Keyboard
Tab into the funnel; arrow keys move between steps, Home and End jump.
Screen readers
A summary gives the first and last steps, the overall conversion and each step's conversion from the previous one.
Table fallback
Screen readers always get a table of the plotted values with the same formats. view="table" shows it at the chart's size.
Report an issueBuilt Oct 21, 2026