Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Charts & Stats

Funnel chart

Charts & Stats

Funnel chart React component for Tailwind CSS v4

Donut chartGauge
Live props
Appearance
variant
curve
dropoffThreshold10%
tone
color
stepColors
radius
Layout
orientation
size
Content
baseline
showConversion
showDropoff
valueFormat
currency
decimalsAuto
locale
label
description
State
defaultValue
loading
Behavior
showTooltip
animated
Code
import { FunnelChart } from "@/components/ui/funnel-chart"

<FunnelChart />
  1. Home
  2. Components
  3. Charts & Stats
  4. Funnel chart
Pro

Funnel chart React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React funnel chart of conversion: each step's count, its conversion and the drop-off between steps, as aligned bars or a tapered shape.

The bars grow in one step after the other the first time the chart scrolls into view while the counts tick up, and each drop-off chip fades in after its row; when the numbers change, the bars glide to their new length. Every number is printed on the row (step, count, conversion, and between rows the drop-off with how many were lost), so there is nothing to hover. When you pass onValueChange or onStepClick the rows become buttons: click or tap one to select it (the others fade to 55%), click it again to clear. With the keyboard the rows are one tab stop: Up / Down (or Left / Right) move between them, Home / End jump to the first and last, Enter or Space select and Escape clears. In the funnel variant the segments are revealed top to bottom (left to right when horizontal); hover a step, or tap it on a phone, to highlight it and read its value, conversion and drop-off in a readout, drag a finger along the funnel to scrub, tap outside to clear. Tab to the funnel and use the arrow keys, Home / End and PageUp / PageDown to walk the steps, Enter to select and Escape to clear; a live region reads each step. A horizontal funnel stacks top to bottom in containers narrower than 480px.

Funnel chart is a Pro React component in the React chart and stat components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add funnel-chart, together with Chart kit, Motion presets, Tones, UIProvider, useControllableState and 1 more and the npm packages motion and d3-shape.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add funnel-chart

Funnel chart is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import FunnelChart from @/components/ui/funnel-chart.

import { FunnelChart } from "@/components/ui/funnel-chart"

const pipeline = [
  { id: "lead", label: "Leads", value: 1240 },
  { id: "qualified", label: "Qualified", value: 620 },
  { id: "proposal", label: "Proposal sent", value: 248 },
  { id: "negotiation", label: "Negotiation", value: 96 },
  { id: "won", label: "Won", value: 41 },
]

export function SalesPipeline() {
  return (
    <FunnelChart
      steps={pipeline}
      locale="en-US"
      label="Sales pipeline, September 2026"
      labels={{
        conversion: (pct, { reference }) => `${pct} of ${reference.toLowerCase()}`,
        dropoff: (pct, lost) => `${pct} · ${lost} lost`,
      }}
      onValueChange={(id) => console.log(id)}
    />
  )
}

Props

  • steps*
    FunnelStep[] = { id: string; label: ReactNode; value: number; description?: ReactNode; name?: string; color?: string }[]

    The steps in order, from the widest to the narrowest. name is the plain-text name when label is not a string; description is a quieter second line; color (a palette slot "series-3", a tone or any CSS color) overrides the fill of that step. Negative values draw as 0.

  • variantdefault "bars"
    "bars" | "funnel"

    bars: one aligned row per step with every number printed (the readable default and the phone layout). funnel: a tapered shape of trapezoids with the labels beside it.

  • orientationdefault "vertical"
    "vertical" | "horizontal"

    Funnel variant: top to bottom, or left to right with the labels above each step. Horizontal falls back to vertical when the chart is narrower than 480px.

  • curvedefault "linear"
    "linear" | "smooth"

    Funnel variant: straight trapezoid sides, or smooth S-curves from one step's width to the next.

  • baselinedefault "first"
    "first" | "previous"

    What the conversion percent is measured against: the first step ("3.3% of leads") or the step before it (step-to-step conversion; the first step then shows none).

  • showConversiondefault true
    boolean

    The conversion percent next to each value.

  • showDropoffdefault true
    boolean

    The chip between steps: how much of the previous step was lost, in percent and in units. A step larger than the one before shows a gain instead.

  • dropoffThresholddefault 10
    number

    Drop-offs from this percent up are printed in the danger text color; smaller ones and gains stay calm. 0 turns the danger color off (every chip muted).

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    The fill of the bars and segments. Neutral is the foreground ink (black in light mode, white in dark mode).

  • colordefault ""
    string

    Any CSS color for the fill; replaces the tone. Empty uses the tone.

  • stepColorsdefault false
    boolean

    Paint each step in its own chart palette slot (series-1, series-2...) instead of one tone.

  • sizedefault "md"
    "sm" | "md" | "lg"

    Bars: track 8 / 12 / 16px, row spacing and text size. Funnel: 200 / 280 / 360px tall.

  • radiusdefault "full"
    "none" | "sm" | "md" | "full"

    The corners of the bars and their tracks (bars variant).

  • value
    string | null

    The selected step id when you control it: the other steps fade to 55%. null clears.

  • defaultValuedefault "null"
    string | null

    The step id selected at first, uncontrolled.

  • onValueChange
    (id: string | null) => void

    Called when a step is selected or cleared. Passing it (or onStepClick) turns the rows into buttons.

  • onStepClick
    (step: FunnelStep, index: number) => void

    Called when a step is clicked, tapped or activated with Enter / Space, e.g. to open the deals in that stage.

  • valueFormatdefault "number"
    ChartValueFormat = "number" | "compact" | "currency" | "percent"

    How the step values print in the rows, the readout and the table. Percent takes whole numbers (12.4 -> "12,4 %").

  • currencydefault "USD"
    string

    ISO 4217 code for valueFormat currency, printed with the narrow symbol ("$128,450").

  • decimalsdefault 0
    number

    Fraction digits for values; auto by magnitude when unset (Auto in the playground): 0 for counts, 1 for percent values.

  • formatValue
    (value: number, context: { series: string; kind: "label" | "tooltip" | "table" }) => string

    Replaces the built-in value formatting everywhere (series is the step id), e.g. compact dollars on the rows and full amounts in the table.

  • localedefault ""
    string

    Locale for numbers and percents. Empty uses the UIProvider / LocaleProvider locale.

  • showTooltipdefault true
    boolean

    Funnel variant: the readout beside a hovered or keyboard-inspected step (pinned above the chart on touch). Bars print every number and need none.

  • animateddefault true
    boolean

    Bars grow and counts tick up on first view, the funnel is revealed top to bottom, and changes glide. Reduced motion always shows the final state.

  • loadingdefault false
    boolean

    Skeleton rows (or a skeleton funnel) in the shape of the chart.

  • emptyState
    ReactNode

    Replaces the built-in empty state (shown when steps is empty).

  • labeldefault ""
    string

    Accessible name of the figure (followed by the overall conversion) and caption of its data table. Empty joins the step names.

  • descriptiondefault ""
    string

    A one-sentence takeaway for screen readers ("The biggest loss is at the proposal stage").

  • labels
    Partial<FunnelChartLabels>

    Strings: empty, loading, inspectHint, selected (appended to the funnel's live readout on the selected step), stepHeader / valueHeader / conversionHeader / dropoffHeader / gainHeader (table and readout), and the functions conversion ((pct, { baseline, reference }) => "50.0% of first"), dropoff ((pct, lost) => "50.0% drop-off, 620 lost"), gain ((pct, gained) => ...), step ((label, value, conversion, change) => the screen reader text) and figure ((label, overall) => ...).

  • classNames
    Partial<Record<FunnelChartSlot, string>>

    Classes for list, step, header, label, description, value, conversion, track, bar, dropoff (bars), svg, segment, stepLabel, tooltip, inspect (funnel) and table.

Parts

  • DEFAULT_FUNNEL_CHART_LABELS

    constant

    The English strings: the shared chart labels plus the keyboard hint, conversion, drop-off and gain lines, each step's spoken sentence and the table headers.

Examples

Funnel shape

variant funnel, vertical and horizontal with smooth sides.

Step to step

baseline previous on a checkout, with a drop-off threshold of 40%.

Step colors

Five recruiting stages, each in its own palette slot.

Money per stage

Pipeline value in compact dollars, brand tone.

Clickable steps

onStepClick opens the deals in that stage (a sheet, bottom on phones).

Gains and zero steps

Re-entries print as a gain; a step at 0 shows 0% and a full drop-off.

Loading and empty

Skeleton rows and the empty state.

Phone, 360px

Selectable rows with the selection held in state.

Dependencies

motiond3-shapechart-kitmotiontonesui-configuse-controllable-stateuse-locale

Files

  • components/ui/funnel-chart.tsx

FAQ

Is the React Funnel chart component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Funnel chart?

Run npx wingo-ui@latest add funnel-chart. It also adds the Wingo UI items it builds on (Chart kit, Motion presets, Tones, UIProvider, useControllableState and 1 more) and the npm packages motion and d3-shape. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/funnel-chart.

How does Funnel chart behave on phones?

In the funnel variant the segments are revealed top to bottom (left to right when horizontal); hover a step, or tap it on a phone, to highlight it and read its value, conversion and drop-off in a readout, drag a finger along the funnel to scrub, tap outside to clear.

See also

Chart kitlibBar chartStepsProgress

Used in

KPI Dashboard

More React chart and stat components

Line chartRadar chartTrend badgeGaugeGitHub ActivityAnimated Counter
All 16 React chart and stat components

Articles using this component

  • React Funnel Chart: Conversion, Drop-off and Cohorts

    Component guides · Nov 6, 2026 · 9 min read

PreviousDonut chartNext Gauge

Sales pipeline, September 2026

Acme CRM · from lead to signed contract

3.3%overall conversion
50% drop-off, 620 lost
60% drop-off, 372 lost
61.3% drop-off, 152 lost
57.3% drop-off, 55 lost
Sales pipeline, September 2026
StepValueConversionDrop-off
Leads1,240100%–
Qualified62050%50% drop-off, 620 lost
Proposal sent24820%60% drop-off, 372 lost
Negotiation967.7%61.3% drop-off, 152 lost
Won413.3%57.3% drop-off, 55 lost

selected: none · tooltip: on · grow-in: on