Funnel Chart
import { FunnelChart } from '@absoluteui/components/funnel-chart';import '@absoluteui/components/funnel-chart/style.css';Using Angular? See Funnel Chart for Angular.
What it does
Section titled “What it does”An accessible SVG funnel chart for sequential stages (for example visits, sign-ups, purchases). It provides:
- one centered bar per stage, its width proportional to the stage value (at least 2 px), joined to the next stage by a decorative trapezoid connector;
- the stage name and value beside the funnel, plus the conversion from the previous stage (
showConversion); - keyboard-reachable stages (one tab stop, arrow keys) whose accessible names read the value and the conversion from the first and the previous stage, with a tooltip on focus and hover;
- a generated summary (overall conversion and the largest drop) and a data table fallback (Stage, Value, Of first stage, Of previous stage).
No animation.
When to use
Section titled “When to use”- A fixed sequence of stages where each stage is a subset of the previous one (conversion or pipeline funnels).
- Showing where the largest drop-off happens between consecutive stages.
When not to use
Section titled “When not to use”- Categories without an order or without a subset relationship: use Bar Chart.
- Comparing several funnels side by side: use a grouped Bar Chart.
- Values that can be negative (rejected by validation).
Examples
Section titled “Examples”Checkout funnel with conversions
Section titled “Checkout funnel with conversions”import { FunnelChart } from '@absoluteui/components/funnel-chart';
const host = document.createElement('div');document.body.append(host);FunnelChart.create(host, { label: 'Checkout funnel', description: 'Last 30 days', stages: [ { id: 'visits', label: 'Visits', value: 12000 }, { id: 'cart', label: 'Added to cart', value: 4100 }, { id: 'checkout', label: 'Checkout', value: 1900 }, { id: 'paid', label: 'Paid', value: 1350 }, ], color: 3,});Compact numbers, no printed conversion, live update
Section titled “Compact numbers, no printed conversion, live update”import { FunnelChart, type FunnelStage } from '@absoluteui/components/funnel-chart';
const host = document.querySelector<HTMLElement>('#pipeline');if (host) { const stages: FunnelStage[] = [ { id: 'leads', label: 'Leads', value: 5400 }, { id: 'qualified', label: 'Qualified', value: 2100 }, { id: 'won', label: 'Won', value: null }, ]; const chart = FunnelChart.create(host, { label: 'Sales pipeline', stages, showConversion: false, valueFormat: { notation: 'compact' }, }); chart.update({ stages: stages.map((s) => (s.id === 'won' ? { ...s, value: 640 } : s)) });}import { FunnelChart } from '@absoluteui/components/funnel-chart';import '@absoluteui/components/funnel-chart/style.css';
const host = document.querySelector<HTMLElement>('#signup');if (host) { FunnelChart.create(host, { label: 'Sign-up funnel', stages: [ { id: 'landing', label: 'Landing page', value: 8200 }, { id: 'form', label: 'Form started', value: 3100 }, { id: 'done', label: 'Account created', value: 2400 }, ], valueFormat: { notation: 'compact' }, });}More usage
Section titled “More usage”import { FunnelChart } from '@absoluteui/components/funnel-chart';
const host = document.createElement('div');document.body.append(host);FunnelChart.create(host, { label: 'Checkout', stages: [ { id: 'visits', label: 'Visits', value: 1000 }, { id: 'cart', label: 'Cart', value: 400 }, { id: 'paid', label: 'Paid', value: 100 }, ],});Anatomy
Section titled “Anatomy”<div class="aui-chart aui-funnel-chart [aui-chart--patterns]"> <div class="aui-chart__header">title, description</div> <ul class="aui-chart__legend" hidden/> <div class="aui-chart__body"> <svg class="aui-chart__svg" role="group" aria-roledescription="funnel chart" aria-labelledby="T" aria-describedby="S"> <g class="aui-funnel-chart__joins" aria-hidden="true"><path class="aui-funnel-chart__join aui-chart__series--c1"/></g> <g class="aui-funnel-chart__stages"> <g class="aui-funnel-chart__stage aui-chart__series--c1"> <rect class="aui-chart__bar aui-chart__mark" role="img" aria-label="Cart: 400, 40% of Visits, 40% of previous stage"/> </g> </g> <g class="aui-funnel-chart__labels" aria-hidden="true"> <text class="aui-funnel-chart__name">Cart</text> <text class="aui-chart__tick-label">400 | 40%</text> </g> </svg> <div class="aui-chart__tooltip" aria-hidden="true" hidden/> </div> <p class="aui-chart__summary" hidden/> <div class="aui-chart__data">Show data table, table</div></div>API reference
Section titled “API reference”Factory
Section titled “Factory”FunnelChart.create(host: HTMLElement, options: FunnelChartOptions): FunnelChartGlobal configuration key: funnelChart (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Chart title: visible text and the accessible name of the plot (aria-labelledby). Must not be blank. Required. | |
hideLabel |
boolean |
false |
Visually hide the title; it stays the accessible name. |
description |
string |
Visible description below the title, also referenced by aria-describedby (text only). | |
summary |
string |
Replaces the generated accessible summary (stage count, first and last stage, overall conversion, largest drop). | |
valueFormat |
Intl.NumberFormatOptions |
Number format for stage values in labels, accessible names, the tooltip, the data table, and the summary. Conversions are always percentages with at most one fraction digit. | |
formatValue |
(value: number) => string |
Custom value text; overrides valueFormat. | |
hiddenSeries |
readonly string[] |
Shared chart option; validated but has no effect (a funnel has no toggleable series). | |
stages |
readonly FunnelStage[] |
Stages in order: { id, label, value: number | null, color?: 1-8 }. Ids are unique and non-empty; values are non-negative; null, NaN, and infinities are a missing stage (read “No value”). Required. | |
color |
ChartColor (1-8) |
1 |
Palette slot for every stage without its own color. |
legend |
'auto' | 'show' | 'hide' |
"auto" |
Shared chart configuration; a funnel never shows a legend (stages are labelled beside their bars). Globally configurable. |
dataTable |
'toggle' | 'visible' | 'hidden' | 'none' |
"toggle" |
Data table fallback (Stage, Value, Of first stage, Of previous stage): behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable. |
tooltip |
boolean |
true |
Tooltip on pointer hover and keyboard focus (value, of first stage, of previous stage). Globally configurable. |
patterns |
boolean |
false |
Shared chart configuration; toggles the aui-chart–patterns host class. Funnel stages draw no textures (there is one series). Globally configurable. |
height |
number |
300 |
Plot height in CSS px (integer 120-2000), divided evenly between stages; the width follows the container. Globally configurable. |
showConversion |
boolean |
true |
Print the conversion from the previous stage next to each stage value (“400 | 40%”). Accessible names, the tooltip, and the table always include conversions. Globally configurable. |
locale |
string |
"en-US" |
Number, percent, and message locale. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
rtl moves stage names and values to the right side and swaps ArrowLeft/ArrowRight. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
The host element. |
element |
SVGSVGElement |
The plot (svg role=“group”), named by the title and described by the summary. |
summary |
string |
The generated (or custom) accessible summary. |
hiddenSeries |
string[] |
Always empty (a funnel has no toggleable series). |
Methods
Section titled “Methods”| Method | Description |
|---|---|
update(options: Partial<FunnelChartOptions>): void |
Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same stage (by id). |
setSeriesVisible(id: string, visible: boolean): void |
Shared chart method; re-renders but has no visible effect on a funnel. Emits no event. |
destroy(): void |
Remove rendering, host classes, listeners, the resize observer, and the configuration subscription. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-chart |
Host (shared chart chrome). |
aui-funnel-chart |
Host modifier for this chart type. |
aui-chart--patterns |
patterns option on (no textures are drawn by a funnel). |
aui-chart__header / __title / __title--hidden / __description / __toolbar |
Title and description; the toolbar stays hidden. |
aui-chart__legend |
Legend list; always hidden for a funnel. |
aui-chart__body / __svg / __layer |
Plot container (height from –aui-chart-height), SVG, and drawing layer. |
aui-chart__series--c1 ... --c8 |
Palette slot classes on each stage and connector; set –aui-chart-color from color-chart-<n>. |
aui-chart__mark / __mark--active / __mark--hover |
Focusable stage bar and its states. |
aui-chart__bar |
Stage bar paint (series color with a surface-colored separator; text-colored outline on hover and focus). |
aui-chart__tick-label |
Value (and conversion) text under each stage name. |
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value / __swatch |
Tooltip (aria-hidden; the focused stage carries the same text). |
aui-chart__empty |
Empty state text (No data). |
aui-chart__summary |
Hidden summary referenced by aria-describedby. |
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric |
Data table fallback. |
aui-funnel-chart__stages / __stage |
Stage bar group and one group per stage. |
aui-funnel-chart__missing |
Missing stage (null value): dashed outline, no fill. |
aui-funnel-chart__joins / __join |
Decorative (aria-hidden) trapezoid connectors between consecutive stages with values. |
aui-funnel-chart__labels / __name |
Stage names and values beside the funnel (aria-hidden). |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”interface FunnelChartConfig extends ChartBaseConfig { showConversion: boolean }interface FunnelStage { id: string; label: string; value: number | null; color?: ChartColor }interface FunnelChartOptions extends ChartCommonOptions, Partial<FunnelChartConfig> { stages: readonly FunnelStage[]; color?: ChartColor;}Accessibility
Section titled “Accessibility”Pattern: SVG funnel chart as a named, described group (role=“group” with aria-roledescription “funnel chart”) of role=“img” stage bars with roving focus; data table fallback (native table: Stage, Value, Of first stage, Of previous stage).
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| ArrowDown / ArrowRight | Stage focused | Next stage (ArrowLeft in RTL). |
| ArrowUp / ArrowLeft | Stage focused | Previous stage (ArrowRight in RTL). |
| Home / End | Stage focused | First / last stage. |
| PageUp / PageDown | Stage focused | Ten stages back / forward (clamped to the first / last). |
| Escape | Tooltip visible | Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move. |
| Tab / Shift+Tab | Any | One tab stop for the plot (the active stage), then the Show data table button and table region. |
| Element | Role |
|---|---|
| svg.aui-chart__svg | group with aria-roledescription (localized “funnel chart”), named by the title |
| stage bars | img with an aria-label: stage name, formatted value, and conversion from the first and previous stage |
| data table | table (native) with caption, column headers, and row headers; wide tables scroll in a focusable region |
| connectors, stage names and values beside the funnel, tooltip | aria-hidden (decorative duplicates of the accessible data) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-labelledby |
svg | id of the visible (or visually hidden) title |
aria-describedby |
svg | description id (when provided) and the generated summary id |
aria-roledescription |
svg | Localized chart type, “funnel chart” |
aria-label |
each stage bar | First stage: “{label}: {value}”; later stages: “{label}: {value}, {ofFirst} of {first}, {ofPrevious} of previous stage” (for example “Cart: 400, 40% of Visits, 40% of previous stage”); missing: “{label}: No value” |
tabindex |
active stage bar | 0 on exactly one stage (roving); other stages have none |
aria-expanded / aria-controls |
Show data table button | Table open state and the table region id |
Roving focus: one stage is in the tab sequence and remembers the last visited stage (by id), also across re-renders (resize, update). Toggling the table keeps focus on the table button.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- Each stage name reads its value and its conversion from the first and the previous stage; the data table lists the same conversions.
- The generated summary names the stage count, the first and last stage with values, the overall conversion, and the largest drop between consecutive stages (for example “Largest drop: Cart to Paid (25% kept).”).
- Meaning never depends on color: bar width, position, and printed names and values carry the data; per-stage colors are optional decoration.
- Forced colors: bars keep a Canvas separator, connectors use GrayText, names CanvasText; focus and hover use Highlight.
- No animation: nothing moves on render; hover and focus emphasis transitions are removed under prefers-reduced-motion and animation: none.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
- aria-roledescription support varies; screen readers without it announce “group”.
Behavior
Section titled “Behavior”States
Section titled “States”default, empty (“No data”: no stages, or no stage above zero), stage missing, stage focused (tooltip), stage hovered, table open.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| plot not focused | Tab | active stage focused, tooltip shown |
| stage focused | arrow keys, Home, End, PageUp, PageDown | another stage focused |
| tooltip visible | Escape | tooltip hidden |
| table closed | Show data table | table shown |
| any | update({ stages }) |
re-rendered; focus stays on the same stage id |
Accessibility notes
Section titled “Accessibility notes”- Stage names read the value and the conversion from the first and previous stage, so the funnel’s meaning is available without seeing bar widths.
- Summary example: “funnel chart, 3 stages, from Visits (1,000) to Paid (100), 10% overall. Largest drop: Cart to Paid (25% kept).”
- Meaning never depends on color: widths, order, and printed text carry the data.
- Forced colors: connectors
GrayText, namesCanvasText, bars keep aCanvasseparator; focus and hover useHighlight. - No animation. Manual screen-reader verification is pending.
Responsive behavior
Section titled “Responsive behavior”Width follows the container. Stage names and values take up to 40% of the width and are truncated with an ellipsis; full text stays in names, tooltip, and table. Reflows at 320 CSS px.
Right-to-left
Section titled “Right-to-left”Stage names and values move to the right of the funnel and are right-aligned; ArrowLeft/ArrowRight swap. The funnel shape is symmetric.
Theming
Section titled “Theming”Stages use color-chart-1..8 (3:1 against surfaces in all themes); connectors use the stage color at low opacity (decorative). Missing stages are a dashed color-chart-axis outline.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { funnelChart: { showConversion: false, dataTable: 'visible' } } });Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
Timezones
Section titled “Timezones”Not applicable (stages are text).
Security
Section titled “Security”All text uses textContent; SVG uses createElementNS; colors are classes; the height and tooltip position use the CSSOM. No innerHTML or style attributes.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry. Values are not logged; validation errors name the option, never its value.
Performance
Section titled “Performance”Budget: create with 20 stages < 20 ms in headless Chromium (e2e performance test), including the first render.
Supported data scale
Section titled “Supported data scale”Up to about 20 stages (each is one focusable node, one connector, two labels). Aggregate longer sequences first.
Edge cases
Section titled “Edge cases”- No stages, or every stage zero or missing: “No data”.
- Missing stage (
null,NaN, infinity): an empty, zero-width dashed placeholder (still focusable), “No value” in its name and the table, no connectors to it; the next stage’s conversion uses the previous stage that has a value. - First (or previous) stage zero or missing: conversions are not computed; the stage reads only its value and the table shows “-”.
- A zero stage is drawn 2 px wide so it stays focusable and visible.
- A later stage larger than an earlier one reads conversions above 100%.
- Long stage names are truncated with an ellipsis beside the funnel.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
FUNNEL_CHART_OPTIONS |
configuration | Blank label; stages not an array; stage not an object; empty or duplicate id; label not a string; negative value; color not 1-8. |
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION |
configuration | Invalid or unknown configuration (for example height outside 120-2000). |
A failed construction leaves the host untouched; a failed update() keeps the previous state.
Known limitations
Section titled “Known limitations”- One funnel per chart, no legend.
legend,patterns, andhiddenSeriesare shared chart options without effect here.- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Negative values; several funnels or stage segments in one chart.
- Curved, pyramid, or proportional-area shapes.
- HTML in labels.