Skip to content

feat(charts): add funnel, retention, and journey visualizations - #57

Merged
robinvrd merged 3 commits into
mainfrom
robin/product-analytics-charts
Oct 9, 2026
Merged

robinvrd merged 3 commits into
mainfrom
robin/product-analytics-charts

Conversation

@robinvrd

@robinvrd robinvrd commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Adds FunnelChart, RetentionChart, and JourneyChart with typed product analytics inputs, adapted from the frontend visualizations and composed through the existing widget workflow.

Includes portion-specific funnel inspection, incomplete retention tails, expandable journey branches, shared square markers, and pointer focus handling. Adds gallery examples and concise API guidance.

Validation: bun run check passes, including 156 tests, package verification, and starter checks. Visually checked desktop and phone layouts in both themes.

Funnel and retention

Funnel and retention charts

Journey

Journey chart

@robinvrd
robinvrd merged commit 48e8e44 into main Oct 9, 2026
6 checks passed
@robinvrd
robinvrd deleted the robin/product-analytics-charts branch October 9, 2026 12:59
@github-actions github-actions Bot mentioned this pull request Oct 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove all images

Comment on lines +13 to +15
export function formatAnalyticsValue(value: number) {
return new Intl.NumberFormat().format(value);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should clean this up and move to our existing helpers. Also, what's an "analytics value"? Prob needs more semantic meaning

Comment on lines +21 to +22
import { chartBarFill } from '@/src/react/ui/chartColor';
export { chartBarFill } from '@/src/react/ui/chartColor';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prob need to clean up our exports so entry paths aren't duplicated.

* Defaults match the shared bar or accent-colored series primitives. */
function ChartLegendMarker({
kind,
kind = 'square',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should perhaps force the agent to pass a deliberate value instead of lazily fall back.

className,
formatValue = formatAnalyticsValue,
}: FunnelChartProps) {
const chartId = useId().replace(/[^a-zA-Z0-9_-]/g, '');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could extract to a Hook to provide as an API.

cancelClear();
clearTimer.current = setTimeout(() => setHighlighted(null), 100);
}
validateAnalyticsIds('funnel step', steps);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hiding a direct call to invariant() doesn't seem like a good pattern

Comment on lines +49 to +56
const label =
outcome === 'truncated'
? 'More steps'
: outcome === 'drop-off'
? 'Drop-off'
: outcome === 'converted'
? 'Converted'
: 'End of path';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be derived from outcome, right?

robinvrd added a commit that referenced this pull request Oct 9, 2026
Addresses the remaining review feedback from #57:

- Remove committed screenshots
([comment](#57 (comment))).
- Reuse `formatNumber()` and `formatPercent()`, replace the generic
analytics helpers, and call `invariant()` directly
([formatting](#57 (comment)),
[validation](#57 (comment))).
- Import `chartBarFill` from its owning module without a duplicate
re-export
([comment](#57 (comment))).
- Require an explicit legend marker kind; built-in charts retain square
markers
([comment](#57 (comment))).
- Expose `useSvgId()` and use it for funnel definitions
([comment](#57 (comment))).
- Derive terminal labels through an outcome mapping
([comment](#57 (comment))).

Breaking API change: `<ChartLegend.Marker>` requires `kind`; pass
`kind="square"` for the shared chart styling.

Validation: `bun run check` passes, including 177 tests, published
declarations, package verification, and starter checks.
leonkenneth pushed a commit that referenced this pull request Oct 9, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.68.0](v0.67.0...v0.68.0)
(2026-10-09)


### ⚠ BREAKING CHANGES

* **charts:** apply post-merge review feedback
([#59](#59))

### Features

* **charts:** add funnel, retention, and journey visualizations
([#57](#57))
([48e8e44](48e8e44))


### Bug Fixes

* **charts:** apply post-merge review feedback
([#59](#59))
([8789d8e](8789d8e))
* **worker:** accept any hyphenated preview host label
([#61](#61))
([28f0bc2](28f0bc2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants