Conversion Funnel
block dashboardHorizontal conversion funnel with count strip above the SmoothFunnel chart and a stage-name + retention-from-previous footer below. Works for hiring (applied → hired), e-commerce (sessions → purchases), onboarding (signed up → activated). 3-6 stages. Theme-aware via OKLCH chart tokens.
Also available for Vue ->Installation
$ pnpm dlx shadcn@latest add https://react.uipkge.dev/r/react/conversion-funnel.json$ npx shadcn@latest add https://react.uipkge.dev/r/react/conversion-funnel.json$ yarn dlx shadcn@latest add https://react.uipkge.dev/r/react/conversion-funnel.json$ bunx shadcn@latest add https://react.uipkge.dev/r/react/conversion-funnel.json
Or with the named registry:
npx shadcn@latest add @uipkge-react/conversion-funnel
Examples
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
Stage interface Stage {
name: string
value: number
} Includes
Theming
CSS custom properties referenced in this item. Override any of them in your :root or per-element to retheme.
--chart-1--chart-2--chart-3--chart-4--chart-5 Files (1)
-
components/blocks/ConversionFunnel.tsx 3.3 kB
/** * Conversion funnel: SmoothFunnel chart with count strip above and * stage-name + retention-from-previous strip below. * * Works for any drop-off flow with 3-6 stages: hiring (applied -> * hired), e-commerce (sessions -> purchases), onboarding (signed up * -> activated), etc. Reads as a single horizontal "flow": * * 72K 38.2K 16.8K 5.6K * ╔══════╗╔════════╗╔══════════╗╔══════════╗ * ║ 100% ║║ 53% ║║ 23% ║║ 8% ║ * ╚══════╝╚════════╝╚══════════╝╚══════════╝ * Views Cart Checkout Purchase * -> 53% -> 44% -> 33% * * The middle pill (inside each band) shows the share OF THE TOP * stage (100%, 53%, 23%, ...). The bottom retention number shows the * stage-to-stage conversion -- usually the more actionable signal. */ import * as React from 'react' import { cn } from '@/lib/utils' import { SmoothFunnel } from '@/components/ui/charts' interface Stage { name: string value: number } export interface ConversionFunnelProps { data: Stage[] /** SmoothFunnel container height. Defaults to 180. */ height?: number | string /** Override colour palette. Defaults to the registry's chart-1..N * OKLCH tokens via CSS variables (so light/dark + theme-customizer * flips ripple through without any JS). Pass a literal hex array to * override. */ colors?: string[] /** Compact number formatter for the count strip (default toLocaleString). */ format?: (n: number) => string /** Hide the retention-from-previous footer on each non-first stage. */ hideRetention?: boolean className?: string } const DEFAULT_PALETTE = [ 'var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)', 'var(--chart-1)', ] export function ConversionFunnel({ data, height = 180, colors, format, hideRetention = false, className, }: ConversionFunnelProps) { const palette = colors ?? DEFAULT_PALETTE const fmt = (v: number) => (format ? format(v) : v.toLocaleString()) const retention = (i: number) => { if (i === 0) return null const prev = data[i - 1]?.value ?? 1 return Math.round((data[i]!.value / prev) * 100) } return ( <div data-uipkge="" data-slot="conversion-funnel" className={cn('space-y-2', className)}> {/* Top: per-stage count */} <div className="grid px-2 text-center" style={{ gridTemplateColumns: `repeat(${data.length}, minmax(0, 1fr))` }} > {data.map((stage) => ( <div key={`top-${stage.name}`} className="text-foreground text-base font-bold tabular-nums"> {fmt(stage.value)} </div> ))} </div> {/* Funnel SVG */} <SmoothFunnel data={data} height={height} colors={palette} /> {/* Bottom: stage name + retention from previous */} <div className="grid px-2 text-center" style={{ gridTemplateColumns: `repeat(${data.length}, minmax(0, 1fr))` }} > {data.map((stage, i) => ( <div key={`bot-${stage.name}`} className="space-y-0.5"> <p className="text-muted-foreground text-xs">{stage.name}</p> {!hideRetention && retention(i) !== null && ( <p className="text-info text-[10px] font-semibold tabular-nums">→ {retention(i)}% retained</p> )} </div> ))} </div> </div> ) }
Raw manifest: https://react.uipkge.dev/r/react/conversion-funnel.json