Skip to content

FRD: Funnel Visualization

Document Summary

FieldDetails
Feature NameFunnel Visualization
StatusDraft
OwnerDavid Holmes
ContributorsDesign, Engineering
Target Releasev2.0.0 (P2)
Related LinksRoadmap item #49
Last Updated2026-05-26

Introduction

Overview

Funnel Visualization is a growth-analytics widget that renders a multi-stage conversion funnel with drop-off percentages and optional CTAs per step. It composes the existing ProgressBar component to visualize stage-to-stage conversion rates. The widget is designed for SaaS dashboards where teams track user progression through signup, activation, and retention funnels.

Goals

  • Deliver a <FunnelVisualization> component that renders an ordered list of funnel stages with conversion rates and drop-off percentages.
  • Compose ProgressBar for per-stage visualization of conversion relative to the first stage.
  • Support an optional CTA button per stage for actionable funnel analysis.
  • Ship Storybook stories with realistic growth analytics data.

Non-Goals

  • Interactive funnel editing or drag-to-reorder stages.
  • Animated transitions between funnel states (deferred to motion enhancement).
  • Horizontal or diagonal funnel shapes (vertical list layout only).
  • Backend funnel calculation or event tracking integration.

Scope

In Scope

AreaDescription
Component<FunnelVisualization> rendering ordered stages with metrics
Stage RenderingEach stage shows name, count, conversion %, and drop-off % from previous stage
Progress BarsProgressBar composition showing conversion relative to stage-1 count
CTAsOptional action button per stage (e.g., “View Users”, “Send Nudge”)
StatesLoading skeleton, empty state, error state
StoriesStorybook stories covering typical funnels, edge cases, and themed variants

Out of Scope

AreaReason
Funnel shape (trapezoid/triangle SVG)Horizontal bar/list layout is more accessible and composable
Branching funnelsLinear funnel only; branching is a different data model
Real-time updatesConsumer handles data refresh
Click-through to filtered user listsApplication-layer concern

Users and Pain Points

User Groups

UserDescriptionNeeds
DevelopersEngineers building growth dashboardsA composable funnel widget that uses DS primitives
Growth PMsProduct managers analyzing conversionVisual funnel with drop-off rates at each stage
DesignersDesign-system consumersToken-aligned funnel that matches the DS visual language

Pain Points

UserPain PointImpact
DevelopersBuilding funnels from scratch using divs and inline stylesInconsistent funnels across products, high development cost
Growth PMsExisting dashboards show raw numbers without visual drop-off indicatorsHarder to identify conversion bottlenecks

Definitions

TermDefinition
FunnelAn ordered sequence of stages through which users progress, with decreasing counts at each stage
Drop-offThe percentage of users who did not progress from one stage to the next
Conversion RateThe percentage of stage-1 users who reached a given stage
Stage CTAAn optional action button associated with a funnel stage

Current State

Existing Behavior

The design system has ProgressBar for single-value progress visualization but no funnel-specific component. Dashboard teams build funnels ad hoc using stacked divs with inline percentage widths.

Current Limitations

  • No funnel component or pattern exists in the design system.
  • ProgressBar is a standalone bar, not designed for sequential stage composition.
  • Drop-off calculation and display are left entirely to consumers.

Existing Workarounds

  • Teams build custom funnel UIs with hardcoded styles and manual percentage calculations.
  • Some teams use third-party chart libraries that do not align with DS tokens.

Proposed Solution

Summary

Introduce <FunnelVisualization> that accepts a stages array where each stage has a name, count, and optional CTA config. The component calculates conversion rates and drop-off percentages automatically, renders each stage as a row with a ProgressBar (width proportional to stage-1 count), stage name, metrics, and optional CTA button.

Key Capabilities

  • Automatic conversion rate and drop-off calculation from raw stage counts.
  • ProgressBar per stage scaled to the first stage’s count (100%).
  • Drop-off indicator between stages showing the percentage lost.
  • Optional CTA button per stage with onClick callback.
  • Accessible summary table for screen readers.

User Experience

Users see a vertical list of funnel stages. Each stage shows a progress bar (wider at top, narrower at bottom), the stage name, user count, conversion rate from stage 1, and the drop-off percentage from the previous stage. Between stages, a subtle connector shows the drop-off. Optional CTA buttons appear on the right side of each stage row.

Developer Experience

<FunnelVisualization
title="Signup Funnel"
stages={[
{ name: "Visited", count: 10000 },
{ name: "Signed Up", count: 3200, cta: { label: "View Users", onClick: () => {} } },
{ name: "Activated", count: 1800 },
{ name: "Subscribed", count: 450 },
]}
/>

Requirements

IDRequirementPriorityNotes
FR-001FunnelVisualization renders ordered stages with progress barsMust-
FR-002Conversion rate and drop-off are auto-calculated from countsMust-
FR-003Each stage can have an optional CTA buttonShould-
FR-004Loading, empty, and error states are supportedMust-
FR-005An accessible data table alternative is available for screen readersMust-

Priority Definitions

PriorityMeaning
MustRequired for this feature to ship.
ShouldImportant, but can be deferred if needed.
CouldNice to have. Not required for initial release.

Functional Requirements

IDRequirementUser BenefitPriority
FUNC-001stages prop accepts { name: string; count: number; cta?: { label: string; onClick: () => void } }[]Simple, typed APIMust
FUNC-002Each stage renders a ProgressBar with width proportional to count / stages[0].count * 100Visual funnel shapeMust
FUNC-003Drop-off percentage between adjacent stages is displayedHighlights conversion bottlenecksMust
FUNC-004Conversion rate from stage 1 is displayed per stageOverall funnel health at a glanceMust
FUNC-005CTA button renders when cta is provided on a stageActionable funnel analysisShould
FUNC-006Stage with count of 0 renders as empty bar with “0%” labelEdge case handlingMust
FUNC-007Single-stage funnel renders without drop-off indicatorsGraceful degenerate caseMust

Non-Functional Requirements

IDRequirementCategoryPriority
NFR-001Renders in under 30ms for funnels with up to 20 stagesPerformanceMust
NFR-002Keyboard-navigable CTA buttons with visible focus ringsAccessibilityMust
NFR-003Works in light and dark themesThemingMust
NFR-004No new runtime dependenciesMaintainabilityMust
NFR-005Percentage calculations handle division by zero (stage-1 count of 0)RobustnessMust

API / Interface Requirements

Public API

NameTypeDescriptionRequired
titlestringFunnel headingNo
stagesFunnelStage[]Ordered array of funnel stagesYes
showDropOffbooleanShow drop-off indicators between stagesNo (default: true)
showConversionRatebooleanShow conversion rate from stage 1No (default: true)
isLoadingbooleanShow loading skeletonNo
errorstringError messageNo
classNamestringAdditional CSS classesNo

FunnelStage Type

interface FunnelStage {
name: string;
count: number;
cta?: {
label: string;
onClick: () => void;
};
}

Example Usage

import { FunnelVisualization } from "@/components/ui/funnel-visualization";
<FunnelVisualization
title="Onboarding Funnel"
stages={[
{ name: "Page View", count: 50000 },
{ name: "Sign Up", count: 12000 },
{ name: "Email Verified", count: 8500 },
{ name: "First Action", count: 3200 },
]}
/>

API Notes

  • stages must have at least one entry; empty array triggers empty state.
  • Drop-off is calculated as (1 - stages[n].count / stages[n-1].count) * 100.
  • Conversion rate is calculated as (stages[n].count / stages[0].count) * 100.

Accessibility Requirements

IDRequirementNotes
A11Y-001A visually-hidden summary table presents funnel data to screen readers&lt;table&gt; with stage name, count, conversion %, drop-off %
A11Y-002Progress bars have aria-valuenow and aria-label with stage name and percentageDelegates to existing ProgressBar a11y
A11Y-003CTA buttons have descriptive aria-label including stage namee.g., “View Users for Sign Up stage”
A11Y-004Drop-off percentages are not conveyed by color aloneText label always present

Checklist

  • Keyboard support is defined.
  • Focus behavior is defined.
  • Screen reader behavior is defined.
  • Color contrast requirements are met.
  • Reduced motion behavior is considered.
  • Semantic HTML expectations are documented.
  • ARIA usage is defined only where needed.

Content and Documentation Requirements

IDRequirementLocationPriority
DOC-001Storybook docs page with overview and props tableStorybookMust
DOC-002”When to use / When not to use” guidanceStorybook docsMust
DOC-003Stories with realistic growth funnel data (signup, activation, retention)StorybookMust
DOC-004Edge case stories (single stage, zero counts, very long funnel)StorybookMust

Dependencies

DependencyTypeOwnerStatusNotes
ProgressBarEngineeringDesign SystemReadyPer-stage bar rendering
ButtonEngineeringDesign SystemReadyStage CTA buttons
Design tokensDesignDesign SystemReadyColor, spacing, typography

Risks and Tradeoffs

Risk / TradeoffImpactMitigation
Vertical list layout is less visually striking than a trapezoid SVG funnelMay not match user expectations from other analytics toolsPrioritize clarity and accessibility; SVG shape can be a future visual enhancement
Auto-calculation of percentages removes consumer controlConsumers with pre-calculated rates cannot use them directlyAdd optional conversionRate and dropOff overrides per stage
Large funnels (20+ stages) may be unwieldy verticallyLong scroll requiredAdd optional maxVisibleStages with “Show more” expansion

Open Questions

IDQuestionOwnerStatusResolution
Q-001Should a trapezoid SVG funnel shape be offered as an alternative variant?David HolmesOpen
Q-002Should stages support a secondary metric (e.g., revenue per stage)?David HolmesOpen
Q-003Should the component support highlighting a specific stage as a bottleneck?David HolmesOpen

Acceptance Criteria

IDCriteriaRelated Requirement
AC-001Funnel renders stages with progressively narrower progress barsFR-001, FUNC-002
AC-002Drop-off percentages display between adjacent stagesFUNC-003
AC-003Conversion rates from stage 1 display per stageFUNC-004
AC-004CTA buttons render and fire onClick when providedFUNC-005
AC-005Empty state renders when stages is emptyFR-004
AC-006Screen reader table presents complete funnel dataA11Y-001
AC-007Zero-count stage renders gracefully without NaNFUNC-006
AC-008All Storybook stories render without errorsDOC-003

LLM Handoff Instructions

Expected LLM Behavior

  • Follow the requirements and acceptance criteria in this document.
  • Do not expand scope beyond the In Scope section.
  • Respect the Out of Scope section.
  • Compose ProgressBar for each stage bar; do not reimplement progress rendering.
  • Use Button for stage CTAs.
  • Calculate conversion and drop-off automatically from stages[n].count.
  • Handle division by zero when stage-1 count is 0.
  • Place stories under the SaaS Widgets Storybook section.

LLM Should Not

  • Build an SVG trapezoid funnel shape.
  • Add third-party charting libraries.
  • Modify the existing ProgressBar component.
  • Add branching or non-linear funnel logic.

Decision Log

DateDecisionReasonOwner
2026-05-26Use vertical list with ProgressBar rather than SVG trapezoidMore accessible, composable, and consistent with DS patternsDavid Holmes
2026-05-26Auto-calculate percentages from raw countsReduces consumer boilerplate and ensures consistencyDavid Holmes

Document History

DateAuthorChange
2026-05-26David HolmesInitial draft