Detent web components
By Shane Logsdon

Charts & metrics

Funnel Chart

Implemented

Conversion funnel with per-stage drop-off and a loss summary

detent-funnel-chart

Port status
Catalog status
implemented
Origin
upstream
Phase
3
Wave
phase-3-data
Group
Charts & metrics

6.3 KB gzip for the class module

Variants

checkout funnel, animation off
no stages (empty state)

Tab into a chart and press ArrowDown to inspect a stage.

Recorded states

  • closed recorded state; no setter
  • reduced motion recorded state; no setter

Usage

Import

import '/components/funnel-chart/define.js';

// or register it yourself
import { DetentFunnelChart } from '/components/funnel-chart/funnel-chart.js';

Attributes

  • animated
  • aria-label
  • show-summary

Properties

  • formatValue
  • stages

Slots

No slots are recorded for this component.

Events

No events are recorded for this component.

Example

Runnable example: site/examples/funnel-chart.ts. The snippet below is generated from the catalogued attributes.

<detent-funnel-chart
  animated
  aria-label="auto-generated"
  show-summary
></detent-funnel-chart>

Property-only values

const element = document.querySelector('detent-funnel-chart');
if (element !== null) {
  // stages: FunnelStage[]
  element.stages = [];
  // formatValue: (n: number) => string
  element.formatValue = () => {};
}

Source

The pinned upstream source for this row:

  • src/components/ui/FunnelChart.tsx sha256 aba263364288…

Native files

The native module and its artifacts:

  • src/components/funnel-chart/funnel-chart.ts
  • src/components/funnel-chart/styles.css
  • src/components/funnel-chart/define.ts
  • docs/components/funnel-chart.md
  • site/examples/funnel-chart.ts
  • tests/browser/funnel-chart.spec.ts
  • evidence/components/funnel-chart.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
animatedanimatedbooleantruePresence semantics: present means true, absent means false.
aria-labelariaLabelstringauto-generatedKebab-case attribute; camelCase property.
show-summaryshowSummarybooleantruePresence semantics: present means true, absent means false.

Properties

Properties
PropertyTypeDefaultNotes
formatValue(n: number) => stringIntl.NumberFormatProperty-only: assign from script; not accepted as an attribute.
stagesFunnelStage[]—Property-only: assign from script; not accepted as an attribute.

Events

No custom events are recorded for this component.

Slots

No slots are recorded for this component.

CSS customisation

  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • className is replaced by the documented CSS parts and custom properties; consumers need no Tailwind.
  • Framer Motion springs and AnimatePresence are replaced by WAAPI entrance motion over opacity/transform; both are removed under reduced motion.
  • React state/hooks are replaced by element-owned state with pre-upgrade property preservation.
  • The bar ramp uses the shared --detent-chart-series-N tokens instead of upstream's color-mix(in oklch, #6d7cff, #34d1bf …), so it adapts to light and dark and every bar keeps ≥ 3:1 against the chart surface (PC-9.5, PC-12.6).
  • Percentages are guarded: when the first stage is 0 the share is shown as — instead of dividing by 1e-9.
  • The pinned source declares no variant prop; the element exposes no variant (confirmed absence, not an omission).
  • Drop chips expose a <title> naming both stages; upstream relies on visual placement alone.

What it does

A conversion funnel: proportional rounded bars, curved bridges showing the users lost between each pair of stages, a drop chip between every pair, a summary line with the overall conversion and the biggest single drop-off, and a screen-reader table mirroring every value. Zero charting dependencies.

Upstream behaviour
  • Proportional stage bars with rounded ends and a color ramp from first to last stage
  • Curved bridges show the users lost between each pair of stages
  • Drop-off chips sit between stages and highlight the hovered step
  • Summary line reports overall conversion and the biggest single drop-off
  • Floating tooltip shows users, percentage of the top stage, and the next loss
  • Container-aware sizing keeps labels and values readable on mobile
  • Keyboard navigation with ArrowUp, ArrowDown, and Escape
  • Screen-reader table mirrors every stage value and percentage
  • prefers-reduced-motion disables bridge and bar entrance animations
Differences from upstream
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • className is replaced by the documented CSS parts and custom properties; consumers need no Tailwind.
  • Framer Motion springs and AnimatePresence are replaced by WAAPI entrance motion over opacity/transform; both are removed under reduced motion.
  • React state/hooks are replaced by element-owned state with pre-upgrade property preservation.
  • The bar ramp uses the shared --detent-chart-series-N tokens instead of upstream's color-mix(in oklch, #6d7cff, #34d1bf …), so it adapts to light and dark and every bar keeps ≥ 3:1 against the chart surface (PC-9.5, PC-12.6).
  • Percentages are guarded: when the first stage is 0 the share is shown as — instead of dividing by 1e-9.
  • The pinned source declares no variant prop; the element exposes no variant (confirmed absence, not an omission).
  • Drop chips expose a <title> naming both stages; upstream relies on visual placement alone.
Previous: Form Next: Glass Navbar

Docs

Components

Project