Funnel Chart
An animated funnel chart with multi-layer halo rings, hover interactions, and staggered entrance animations
Preview
Installation
pnpm dlx shadcn@latest add @bklit/funnel-chartUsage
The Funnel Chart is a standalone component that renders an animated funnel visualization. Each segment represents a stage in a pipeline, with the width (or height in vertical mode) proportional to the value.
import { FunnelChart } from "@bklitui/ui/charts";
const data = [
{ label: "Visitors", value: 12400, displayValue: "12.4k" },
{ label: "Leads", value: 6800, displayValue: "6.8k" },
{ label: "Qualified", value: 3200, displayValue: "3.2k" },
{ label: "Proposals", value: 1500, displayValue: "1.5k" },
{ label: "Closed", value: 620, displayValue: "620" },
];
export default function SalesFunnel() {
return (
<FunnelChart
data={data}
color="var(--chart-1)"
layers={3}
/>
);
}Props
FunnelChart
| Prop | Type | Default | Description |
|---|---|---|---|
data | FunnelStage[] | required | Array of funnel stages |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction |
color | string | "var(--chart-1)" | Default color for all segments |
layers | number | 3 | Number of concentric halo rings per segment |
edges | "curved" | "straight" | "curved" | Edge style for segment shapes |
gap | number | 4 | Gap between segments in pixels |
staggerDelay | number | 0.12 | Stagger delay between segment animations (seconds) |
showPercentage | boolean | true | Show percentage badges |
showValues | boolean | true | Show value labels |
showLabels | boolean | true | Show stage name labels |
formatPercentage | (pct: number) => string | rounds to integer | Custom percentage formatter |
formatValue | (value: number) => string | locale string | Custom value formatter |
labelLayout | "spread" | "grouped" | "spread" | How labels are arranged within each segment |
labelOrientation | "vertical" | "horizontal" | auto | Stack direction for grouped labels |
labelAlign | "center" | "start" | "end" | "center" | Alignment of grouped labels |
hoveredIndex | number | null | - | Controlled hover state (segment index) |
onHoverChange | (index: number | null) => void | - | Callback when hover state changes |
grid | boolean | GridConfig | false | Background bands and grid lines |
renderPattern | (id: string, color: string) => ReactNode | - | Custom SVG pattern for the innermost ring |
className | string | - | Additional CSS class |
style | CSSProperties | - | Additional inline styles |
FunnelStage
| Property | Type | Description |
|---|---|---|
label | string | Stage name displayed below the segment |
value | number | Numeric value (first item is treated as 100%) |
displayValue | string? | Custom display string (overrides formatted value) |
color | string? | Override the chart-level color for this segment |
gradient | FunnelGradientStop[]? | Linear gradient for this segment |
GridConfig
When passing an object to grid, the following options are available:
| Property | Type | Default | Description |
|---|---|---|---|
bands | boolean | true | Show alternating background bands |
bandColor | string | "var(--color-muted)" | Color of the background bands |
lines | boolean | true | Show grid lines between segments |
lineColor | string | "var(--chart-grid)" | Color of the grid lines |
lineOpacity | number | 1 | Opacity of the grid lines |
lineWidth | number | 1 | Width of the grid lines in pixels |
See the charts gallery for vertical layouts, per-segment colors, patterns, and legend sync.