termino
~/docs/custom/funnel

FunnelChartcustom

Centered shrinking bars with per-stage gradient and percent

~/custom/funnel
live
$ termino funnel — activation
████████████████████████████ visitors 100%
██████████ signups 35%
████ activated 15%
paying 5%
churned 1%
static centered bars — cyan→red gradient by stage

##API

One row per stage. Bar width scales with `value/max`, centered in the canvas, followed by the stage label and a right-aligned percent. Colors lerp `baseColor → endColor` across stages unless a stage provides its own `color`.

properties
proptypedefaultdescription
stages{ label, value, color? }[]-Stages in funnel order
widthnumber42Canvas width
showPercentbooleantrueRight-aligned percent of max
baseColor / endColorstringcyan / redGradient endpoints

##Keymap

~/keymap
Display only

##Notes

  • Percent is relative to the largest stage, not the first — churn shows honest drop-off.
  • Swap in `color` per stage for threshold-based coloring.

##Source

Real implementation — this is the code that runs in your terminal.

tsxfunnel.tsx
1import { createElement as h, useMemo } from "react";
2import { Canvas } from "./canvas";
3import { renderFunnel, type FunnelStage } from "./chart";
4
5export interface FunnelChartProps {
6 stages: FunnelStage[];
7 width?: number;
8 showPercent?: boolean;
9 baseColor?: string;
10 endColor?: string;
11}
12
13export function FunnelChart({
14 stages,
15 width = 42,
16 showPercent,
17 baseColor,
18 endColor,
19}: Readonly<FunnelChartProps>) {
20 const rows = useMemo(
21 () => renderFunnel(stages, width, { showPercent, baseColor, endColor }),
22 [stages, width, showPercent, baseColor, endColor],
23 );
24 return h("box", { flexDirection: "column", gap: 0, width }, h(Canvas, { rows, width }));
25}
26