feat: Feature Analytics label grouping (#6067)#7215
feat: Feature Analytics label grouping (#6067)#7215talissoncosta wants to merge 10 commits intofix/storybook-dark-modefrom
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Zero custom CSS — tooltip uses Bootstrap utilities + semantic tokens. ChartTooltip extracted to own file for single responsibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Data utilities extracted to analyticsUtils.ts for testability. Closes #6067 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Chart tokens were sorted alphabetically (1, 10, 2, 3...) instead of numerically (1, 2, 3...10). Use localeCompare with numeric option. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update featureAnalytics service queryFn to return rawEntries alongside chartData, so FeatureAnalytics doesn't need to call hooks in a loop - Remove useGetEnvironmentAnalyticsQuery calls inside .map() (React rules-of-hooks violation) - Rename analyticsUtils.ts to utils.ts - Add 14 unit tests for hasLabelledData, aggregateByLabels, buildEnvColorMap - Fix natural sort order in token generator Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add useChartColors() and useChartColorMap() hooks (common/hooks/) - Remove getCSSVars/CHART_COLOURS imports from utils.ts — colors are now passed as a parameter from the hook - Remove buildEnvColorMap — replaced by useChartColorMap hook - Update tests to pass mock colors directly (no jest.mock needed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace getCSSVars/CHART_COLOURS with useChartColorMap hook - Replace inline color/fontSize/margin styles with Bootstrap utilities Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove common/utils/getCSSVar.ts — only had one consumer - Inline resolveColors() into useChartColors hook with JSDoc explaining why we read from DOM (Recharts needs hex strings, not var() refs) - Add comment on rawEntries in service queryFn explaining the dual return (chartData for environments, rawEntries for labels) - Add comment on label priority in utils.ts - Regenerate tokens.ts with updated comment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, reopen this pull request to trigger a review.
Docker builds report
|
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
|
Visual Regression16 screenshots compared. See report for details. |
|
|
||
| /** | ||
| * Reads the computed value of CSS custom properties from the document root. | ||
| * |
There was a problem hiding this comment.
Recharts' fill prop needs hex strings, not CSS var refs. getComputedStyle resolves to the current theme value automatically (dark mode respected).
| } | ||
|
|
||
| // Collect raw entries with labels intact for label-based grouping. | ||
| // chartData aggregates by environment (existing behaviour), |
There was a problem hiding this comment.
chartData = existing environment aggregation. rawEntries = new, preserves per-entry labels so FeatureAnalytics can group by SDK without calling hooks inside a loop (was a rules-of-hooks violation).
| import React, { FC } from 'react' | ||
| import { | ||
| Bar, | ||
| BarChart as RawBarChart, |
There was a problem hiding this comment.
Alias to avoid shadowing — our component is named BarChart which would collide with the Recharts import.
| height={80} | ||
| angle={-90} | ||
| textAnchor='end' | ||
| tick={{ dx: -4, fill: '#656D7B', fontSize: 11 }} |
There was a problem hiding this comment.
#656D7B is --slate-500. Recharts tick/axis props need hex strings (same limitation as fill). Consistent with existing Recharts usage. Could use axis colour tokens in a follow-up.
| dataKey={label} | ||
| stackId={stacked ? 'series' : undefined} | ||
| fill={colorMap.get(label) || '#656D7B'} | ||
| animationBegin={index * 80} |
There was a problem hiding this comment.
Staggered bar entrance — each series starts 80ms after the previous. Uses Recharts built-in animation, not the motion library.
| className={classNames('d-inline-block flex-shrink-0 rounded-xs', className)} | ||
| style={{ | ||
| backgroundColor: color, | ||
| height: SIZE_MAP[size], |
There was a problem hiding this comment.
backgroundColor is dynamic (per instance). height/width have no Bootstrap utility for 8/12/16px. borderRadius uses the rounded-xs token class.
| rawData.forEach((entry) => { | ||
| const date = entry.day | ||
| // Priority: user_agent (SDK name) > client_application_name > 'Unknown' | ||
| const labelValue = |
There was a problem hiding this comment.
Priority from backend: user_agent (SDK name, most useful) > client_application_name (fallback) > Unknown (empty/missing labels).
| --red-200: #f9cbc9; | ||
| --red-300: #f5a5a2; | ||
| --red-400: #f57c78; | ||
| --red-50: #fef2f1; |
There was a problem hiding this comment.
Not duplication — first block is :root (light, 500/600 shades), this block is .dark (lighter 300/400 shades for contrast on dark backgrounds). Same pattern as all other semantic tokens.
docs/if required so people know about the feature.Changes
Closes #6067
Feature Analytics label grouping
When the API returns labelled evaluation buckets (e.g. different SDKs), the chart now stacks bars by label value with different colours, and shows a MultiSelect filter to show/hide specific labels. Falls back to environment-based grouping when no labels are present.
New infrastructure
web/components/charts/BarChart.tsx)web/components/charts/ChartTooltip.tsx)web/components/ColorSwatch.tsx)common/utils/getCSSVar.ts)--color-chart-1through--color-chart-10with light/dark variants.CHART_COLOURSarray export.hasLabelledData,aggregateByLabels,buildEnvColorMap).Storybook stories
How did you test this code?
In Storybook
npm run storybookIn the app
ENV=local npm run devAutomated
npx eslint— 0 errorsnpm run typecheck— 0 new errors🤖 Generated with Claude Code