From 3bf21e65abf7ff1baa8c79e5fcef9330039fd2bc Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 11 Mar 2026 02:05:23 +0000 Subject: [PATCH 1/5] Charts: Standardize legend stories and documentation across all chart types CHARTS-183: Standardize legend stories to exactly two per chart type (WithLegend and WithCompositionLegend) and update Legend component docs to use composition API as the primary integration example. Story changes per chart: - BarChart: Replace WithInteractiveLegend with WithLegend, remove CustomLegendPositioning - LineChart: Replace WithInteractiveLegend with WithLegend, remove CustomLegendPositioning - PieChart: Remove InteractiveLegend and CustomLegendPositioning - Donut: Remove InteractiveLegend, CustomLegendPositioning, and CustomLegend - PieSemiCircleChart: Remove InteractiveLegend and CustomLegendPositioning - LeaderboardChart: Remove CustomLegendLabels and InteractiveLegend Documentation changes: - Update Legend docs Integration with Charts section to lead with composition API pattern - Update overview code example to show composition API first - Update interactive legend docs to show composition approach - Update Legend component stories to use composition API for chart integration examples (WithLineChart, WithBarChart) - Add consistent descriptions to all WithLegend and WithCompositionLegend stories Co-authored-by: Adam Wood --- ...HARTS-183-legend-stories-and-documentation | 4 + .../bar-chart/stories/index.stories.tsx | 33 +-- .../stories/index.stories.tsx | 41 +--- .../line-chart/stories/index.stories.tsx | 32 +-- .../pie-chart/stories/donut.stories.tsx | 188 +----------------- .../pie-chart/stories/index.stories.tsx | 89 +-------- .../stories/index.stories.tsx | 85 +------- .../components/legend/stories/index.docs.mdx | 82 ++++---- .../legend/stories/index.stories.tsx | 55 ++--- 9 files changed, 106 insertions(+), 503 deletions(-) create mode 100644 projects/js-packages/charts/changelog/CHARTS-183-legend-stories-and-documentation diff --git a/projects/js-packages/charts/changelog/CHARTS-183-legend-stories-and-documentation b/projects/js-packages/charts/changelog/CHARTS-183-legend-stories-and-documentation new file mode 100644 index 000000000000..5667330bdf98 --- /dev/null +++ b/projects/js-packages/charts/changelog/CHARTS-183-legend-stories-and-documentation @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Standardize legend stories and documentation across all chart types. diff --git a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx index a7cd75c1e30c..6b2eadd70104 100644 --- a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx @@ -238,18 +238,16 @@ SmartFormatting.parameters = { }, }; -export const WithInteractiveLegend: Story = { +export const WithLegend: Story = { args: { ...Default.args, showLegend: true, - legendInteractive: true, - chartId: 'bar-chart-with-interactive-legend', }, parameters: { docs: { description: { story: - 'Bar chart with interactive legend. Click on legend items to toggle series visibility. When all series are hidden, a message will be displayed prompting you to click legend items to show data again.', + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', }, }, }, @@ -269,32 +267,7 @@ export const WithCompositionLegend: StoryObj< typeof BarChart > = { docs: { description: { story: - 'Demonstrates using the composition API with `` as a child component. This provides the same functionality as the `showLegend` prop but allows for more flexible composition patterns.', - }, - }, - }, -}; - -// Story showcasing legend customization controls -export const CustomLegendPositioning: Story = { - args: { - withTooltips: true, - data: medalCountsData.slice( 0, 3 ), // Use first 3 series for cleaner legend - gridVisibility: 'x', - maxWidth: 1200, - resizeDebounceTime: 300, - containerHeight: '400px', - // showLegend defaults to false, explicitly enabling for demonstration - showLegend: true, - legendOrientation: 'vertical', - legendAlignment: 'start', - legendPosition: 'top', - }, - parameters: { - docs: { - description: { - story: - 'Bar chart with top-left positioned vertical legend. This demonstrates non-default legend positioning to showcase different legend placement possibilities.', + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, diff --git a/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx index dc4737414276..ef0ce353994a 100644 --- a/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx @@ -384,17 +384,12 @@ export const WithLegend: Story = { loading: false, showLegend: true, }, -}; - -export const CustomLegendLabels: Story = { - args: { - data: sampleData, - withComparison: true, - loading: false, - showLegend: true, - legendLabels: { - primary: 'Aug 11-Sep 9, 2025', - comparison: 'Jul 11-Aug 11, 2025', + parameters: { + docs: { + description: { + story: + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', + }, }, }, }; @@ -424,29 +419,7 @@ export const WithCompositionLegend: Story = { docs: { description: { story: - 'Demonstrates the composition API allowing flexible component composition. The chart can be used with traditional props or with explicit child components for more control over legend positioning and styling.', - }, - }, - }, -}; - -export const InteractiveLegend: Story = { - args: { - data: sampleData, - withComparison: true, - loading: false, - showLegend: true, - legendInteractive: true, - legendLabels: { - primary: 'Current period', - comparison: 'Previous period', - }, - }, - parameters: { - docs: { - description: { - story: - 'Interactive legend allows users to click legend items to toggle the visibility of current and previous period data. Click on the legend items to show/hide the corresponding bars and values. When all series are hidden, a message is displayed.', + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, diff --git a/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx index ab4b07a05934..bd6a459053bf 100644 --- a/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx @@ -141,38 +141,17 @@ Animation.args = { animation: true, }; -export const WithInteractiveLegend: StoryObj< typeof LineChart > = Template.bind( {} ); -WithInteractiveLegend.args = { +export const WithLegend: StoryObj< typeof LineChart > = Template.bind( {} ); +WithLegend.args = { ...lineChartStoryArgs, - chartId: 'interactive-legend-demo', showLegend: true, - legendInteractive: true, }; -WithInteractiveLegend.parameters = { +WithLegend.parameters = { docs: { description: { story: - 'Line chart with interactive legend. Click or tap legend items to toggle series visibility. Use Tab to focus legend items, then Enter or Space to toggle. Series colors remain stable when toggling visibility.', - }, - }, -}; - -export const CustomLegendPositioning: StoryObj< typeof LineChart > = Template.bind( {} ); -CustomLegendPositioning.args = { - ...lineChartStoryArgs, - showLegend: true, - legendAlignment: 'start', - legendPosition: 'top', - legendOrientation: 'horizontal', - withLegendGlyph: true, -}; - -CustomLegendPositioning.parameters = { - docs: { - description: { - story: - 'Line chart with top-left positioned horizontal legend. This demonstrates non-default legend positioning to showcase different legend placement possibilities with temperature data for London, Canberra, and Mars.', + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', }, }, }; @@ -190,7 +169,8 @@ export const WithCompositionLegend: StoryObj< typeof LineChart > = { parameters: { docs: { description: { - story: 'Legend used with LineChart using the composition API, positioned below the chart.', + story: + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx index 7babb98bcd80..cbb2cb1d787d 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx @@ -1,11 +1,3 @@ -/* eslint-disable @wordpress/no-unsafe-wp-apis */ -import { - __experimentalText as WPText, - __experimentalHStack as HStack, -} from '@wordpress/components'; -import { Fragment } from 'react'; -import { BaseLegendItem } from '../../../components/legend/types'; -import { GlobalChartsProvider } from '../../../providers'; import { chartDecorator, sharedChartArgTypes, @@ -15,10 +7,9 @@ import { legendArgTypes, themeArgTypes, } from '../../../stories'; -import { customerRevenueData, customerRevenueLegendData } from '../../../stories/sample-data'; import { Group } from '../../../visx/group'; import { Text } from '../../../visx/text'; -import { PieChart, PieChartUnresponsive } from '../../pie-chart'; +import { PieChart } from '../../pie-chart'; import type { Meta, StoryObj } from '@storybook/react'; type StoryArgs = ChartStoryArgs< React.ComponentProps< typeof PieChart > >; @@ -217,6 +208,14 @@ export const WithLegend: Story = { showLegend: true, containerHeight: '500px', }, + parameters: { + docs: { + description: { + story: + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', + }, + }, + }, }; export const WithCompositionLegend: Story = { @@ -244,176 +243,9 @@ export const WithCompositionLegend: Story = { docs: { description: { story: - 'Demonstrates the donut chart composition API, allowing flexible combination of chart elements and legends.', - }, - }, - }, -}; - -export const InteractiveLegend: Story = { - render: args => ( - - - - - User Stats - - - 100K Total - - -

- Click legend items to show/hide segments. The total value updates dynamically. -

-
-
- ), - args: { - data, - thickness: 0.5, - legendInteractive: true, - }, - parameters: { - docs: { - description: { - story: - 'Interactive donut chart with clickable legend. Segments can be hidden/shown, and percentages recalculate automatically. Requires chartId and GlobalChartsProvider.', + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, }; -export const CustomLegendPositioning: Story = { - args: { - ...Default.args, - thickness: 0.4, - showLegend: true, - legendOrientation: 'vertical', - legendAlignment: 'start', - legendPosition: 'top', - containerHeight: '450px', - data: [ - { - label: 'Desktop', - value: 45000, - valueDisplay: '45K', - percentage: 45, - }, - { - label: 'Mobile', - value: 35000, - valueDisplay: '35K', - percentage: 35, - }, - { - label: 'Tablet', - value: 20000, - valueDisplay: '20K', - percentage: 20, - }, - ], - children: ( - - - Distribution - - - ), - }, - parameters: { - docs: { - description: { - story: 'Donut chart with vertical legend positioned at the top left.', - }, - }, - }, -}; - -const CustomPieLegend = ( { - chartItems, - items, - withComparison, -}: { - chartItems: BaseLegendItem[]; - items: { label: string; value: number; formattedValue: string; comparison: string }[]; - withComparison: boolean; -} ) => ( -
- { items.map( ( item, index ) => { - const { color } = chartItems[ index ]; - - return ( - - -
- { item.label } - - - { item.formattedValue } - - - { withComparison && item.comparison } - - - ); - } ) } -
-); - -export const CustomLegend: Story = { - render: args => ( - - ( - - ) } - /> - - ), - args: { - ...Default.args, - data: customerRevenueData, - showLabels: false, - thickness: 0.3, - cornerScale: 0.03, - gapScale: 0.01, - size: 164, - withComparison: true, - withTooltips: false, - containerHeight: '300px', - }, - parameters: { - docs: { - description: { - story: 'Demonstrates how to customize the legend using the render prop.', - }, - }, - }, -}; diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx index e7e2b349a8b3..4512aa5a9956 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx @@ -180,6 +180,14 @@ export const WithLegend: Story = { ...Default.args, showLegend: true, }, + parameters: { + docs: { + description: { + story: + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', + }, + }, + }, }; export const WithCompositionLegend: Story = { @@ -198,86 +206,7 @@ export const WithCompositionLegend: Story = { docs: { description: { story: - 'Demonstrates the new composition API allowing flexible component composition. The chart can be used with traditional props or with explicit child components for more control.', - }, - }, - }, -}; - -export const InteractiveLegend: Story = { - render: args => ( - - -

- Click legend items to show/hide segments. Percentages recalculate automatically for - visible segments. -

-
-
- ), - args: { - data, - size: 400, - legendInteractive: true, - }, - parameters: { - docs: { - description: { - story: - 'Interactive legends allow users to toggle segment visibility by clicking legend items. When segments are hidden, the visible segments are recalculated to total 100%. Requires chartId and GlobalChartsProvider.', - }, - }, - }, -}; - -export const CustomLegendPositioning: Story = { - args: { - data: [ - { - label: 'Desktop', - value: 45000, - valueDisplay: '45K', - percentage: 45, - }, - { - label: 'Mobile', - value: 35000, - valueDisplay: '35K', - percentage: 35, - }, - { - label: 'Tablet', - value: 20000, - valueDisplay: '20K', - percentage: 20, - }, - ], - thickness: 1, // Full pie chart - gapScale: 0.03, - padding: 20, - cornerScale: 0.03, - withTooltips: true, - showLegend: true, - legendOrientation: 'vertical', - legendAlignment: 'center', - legendPosition: 'top', - legendShape: 'circle', - size: 400, - containerWidth: '432px', - containerHeight: '432px', - }, - parameters: { - docs: { - description: { - story: - 'Pie chart with top-end positioned vertical legend. This demonstrates non-default legend positioning to showcase different legend placement possibilities with device usage data.', + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, diff --git a/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx index b65fa39b869c..ab093da90a46 100644 --- a/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx @@ -1,6 +1,5 @@ import { Group } from '@visx/group'; import { Text } from '@visx/text'; -import { GlobalChartsProvider } from '../../../providers'; import { chartDecorator, sharedChartArgTypes, @@ -141,6 +140,14 @@ export const WithLegend: Story = { ...Default.args, showLegend: true, }, + parameters: { + docs: { + description: { + story: + 'Props-based legend using `showLegend` and the `legend` config object. Use Storybook controls to adjust legend position, alignment, orientation, shape, and interactivity.', + }, + }, + }, }; export const WithCompositionLegend: Story = { @@ -159,81 +166,7 @@ export const WithCompositionLegend: Story = { docs: { description: { story: - 'Demonstrates the semi-circle chart composition API, allowing flexible component composition with explicit legend placement.', - }, - }, - }, -}; - -export const InteractiveLegend: Story = { - render: args => ( - - -

- Click legend items to show/hide segments. Percentages adjust automatically. -

-
-
- ), - args: { - data, - legendInteractive: true, - }, - parameters: { - docs: { - description: { - story: - 'Interactive semi-circle chart with clickable legend items. Hidden segments are excluded and percentages recalculate. Requires chartId and GlobalChartsProvider.', - }, - }, - }, -}; - -export const CustomLegendPositioning: Story = { - args: { - thickness: 0.4, - data: [ - { - label: 'MacOS', - value: 30000, - valueDisplay: '30K', - percentage: 30, - }, - { - label: 'Linux', - value: 22000, - valueDisplay: '22K', - percentage: 22, - }, - { - label: 'Windows', - value: 48000, - valueDisplay: '48K', - percentage: 48, - }, - ], - label: 'OS', - note: 'Windows +10%', - withTooltips: true, - showLegend: true, - legendOrientation: 'vertical', - legendAlignment: 'end', - legendPosition: 'top', - legendShape: 'circle', - }, - parameters: { - docs: { - description: { - story: - 'Semi-circle pie chart with right-top positioned vertical legend. This demonstrates non-default legend positioning to showcase different legend placement possibilities with OS usage data.', + 'Composition API using `` as a child component for explicit legend placement and configuration. This is the recommended approach for flexible legend positioning.', }, }, }, diff --git a/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx b/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx index ebf60b4e8e51..ef63747c939f 100644 --- a/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx +++ b/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx @@ -17,6 +17,12 @@ The Legend component offers multiple ways to display chart legends, from simple language="tsx" code={ `import { Legend, LineChart } from '@automattic/charts'; + // Composition API (recommended) + + + + + // Standalone usage with manual data - - // Automatic data from chart context - - - ` + />` } /> ## API Reference @@ -93,52 +94,44 @@ For detailed information about all optional props, see the [Legend API Reference ## Integration with Charts -### Using with LineChart +### Composition API (Recommended) -Legends can be positioned independently from the chart, retrieving data automatically via hooks: +The recommended way to add legends to charts is the composition API. Use the chart's `Legend` compound component as a child for explicit placement and configuration: - ` } -/> + code={ `import { LineChart } from '@automattic/charts'; -### Using with BarChart + + + ` } +/> -Position legends vertically beside charts for a side-by-side layout: +This works with all chart types that support legends: - - -
` } + + + ` } /> +#### Key Benefits + +- **Explicit Placement**: The legend is part of the chart's component tree, making placement clear and predictable +- **Automatic Data**: Legend items are derived from the chart's data automatically +- **Full Configuration**: Supports all legend props including `position`, `alignment`, `orientation`, `shape`, and `interactive` +- **Type Safety**: Full TypeScript support with chart-specific legend types + ### Standalone Legend with Chart Context -The Legend component's most powerful feature is its ability to automatically retrieve data from charts using the chart context: +For decoupled layouts such as dashboards, the Legend component can retrieve data from charts automatically using the chart context: @@ -169,13 +162,6 @@ The Legend component's most powerful feature is its ability to automatically ret 2. **Data Retrieval**: The Legend component can then retrieve this data using the same `chartId` 3. **Decoupled Display**: The legend can be placed anywhere in your layout, completely independent from the chart -#### Key Benefits - -- **Flexible Layouts**: Create complex dashboard layouts with centralized legend areas -- **Consistent Legends**: Multiple charts can share legend styles and positioning -- **Dynamic Updates**: Legend automatically updates when chart data changes -- **No Prop Drilling**: No need to pass legend data through multiple component levels - #### Important Notes - The chart and legend must be wrapped in the same GlobalChartsProvider context @@ -189,7 +175,7 @@ Interactive legends allow users to toggle series visibility by clicking or using ### Basic Interactive Legend -Enable interactive legends by setting `legend.interactive` on the chart. When `showLegend` is enabled, the chart's built-in legend will automatically become interactive: +Enable interactive legends using the composition API by passing `interactive` to the chart's Legend compound component: @@ -197,8 +183,18 @@ Enable interactive legends by setting `legend.interactive` on the chart. When `s language="tsx" code={ `import { LineChart } from '@automattic/charts'; - + + ` } +/> + +Alternatively, use the props-based approach with `showLegend` and the `legend` config object: + +` } diff --git a/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx b/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx index 72c4fa00b44f..26da6d4a58a2 100644 --- a/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx @@ -8,7 +8,6 @@ import { themeArgTypes, sharedThemeArgs, } from '../../../stories'; -import { useChartLegendItems } from '../hooks/use-chart-legend-items'; import { Legend } from '../legend'; import type { SeriesData, DataPointPercentage } from '../../../types'; @@ -106,45 +105,29 @@ export const Vertical: Story = { }, }; -// Story showing use with LineChart data -const WithLineChartData = () => { - const legendItems = useChartLegendItems( lineChartData, { - showValues: false, - } ); - - return ( -
- - -
- ); -}; - +// Story showing composition API with LineChart export const WithLineChart: Story = { - render: () => , -}; - -// Story showing use with BarChart data -const WithBarChartData = () => { - const legendItems = useChartLegendItems( barChartData ); - - return ( -
- - -
- ); + render: () => ( + + + + ), }; +// Story showing composition API with BarChart export const WithBarChart: Story = { - render: () => , + render: () => ( + + + + ), }; // Story showing standalone legend using chartId to automatically get data from context From 2135f5abfcad73d932a4e48465fa924599f70133 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 11 Mar 2026 02:14:11 +0000 Subject: [PATCH 2/5] Fix trailing newline lint issue in donut.stories.tsx Co-authored-by: Adam Wood --- .../charts/src/charts/pie-chart/stories/donut.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx index cbb2cb1d787d..713e62742354 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx @@ -248,4 +248,3 @@ export const WithCompositionLegend: Story = { }, }, }; - From c873ac3d75294ff4ede6e3d94ec43ea802b16a81 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:43:08 +1300 Subject: [PATCH 3/5] fix(charts): Wire up legend interactivity in composition stories WithCompositionLegend stories were passing legend config only to the child Legend component, not the parent chart. This meant toggling legendInteractive in Storybook rendered toggle buttons but the chart never filtered series visibility. Pass legend={ { interactive } } to the parent chart in all six composition stories (bar, line, pie, donut, semi-circle, leaderboard). The narrowed object avoids ChartLegendConfig type mismatches. Refs: CHARTS-187 --- .../charts/src/charts/bar-chart/stories/index.stories.tsx | 7 ++++++- .../charts/leaderboard-chart/stories/index.stories.tsx | 6 +++++- .../src/charts/line-chart/stories/index.stories.tsx | 7 ++++++- .../charts/src/charts/pie-chart/stories/donut.stories.tsx | 8 +++++++- .../charts/src/charts/pie-chart/stories/index.stories.tsx | 6 +++++- .../pie-semi-circle-chart/stories/index.stories.tsx | 7 ++++++- 6 files changed, 35 insertions(+), 6 deletions(-) diff --git a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx index 6b2eadd70104..4051720d3a10 100644 --- a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx @@ -258,7 +258,12 @@ export const WithCompositionLegend: StoryObj< typeof BarChart > = { render: args => { const legend = extractLegendConfig( args ); return ( - + ); diff --git a/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx index ef0ce353994a..667c0c4f5497 100644 --- a/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/leaderboard-chart/stories/index.stories.tsx @@ -398,7 +398,11 @@ export const WithCompositionLegend: Story = { render: args => { const legend = extractLegendConfig( args ); return ( - + = { render: args => { const legend = extractLegendConfig( args ); return ( - + ); diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx index 713e62742354..bf7233d8a90c 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx @@ -222,7 +222,13 @@ export const WithCompositionLegend: Story = { render: args => { const legend = extractLegendConfig( args ); return ( - + User Stats diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx index 4512aa5a9956..f8abca4d2fa7 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/index.stories.tsx @@ -194,7 +194,11 @@ export const WithCompositionLegend: Story = { render: args => { const legend = extractLegendConfig( args ); return ( - + ); diff --git a/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx index ab093da90a46..280470d9cd25 100644 --- a/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-semi-circle-chart/stories/index.stories.tsx @@ -154,7 +154,12 @@ export const WithCompositionLegend: Story = { render: args => { const legend = extractLegendConfig( args ); return ( - + ); From 8db0043d6bc4f99b76d5ed64fa6e974344cd01d7 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:53:26 +1300 Subject: [PATCH 4/5] fix(charts): Restore CustomLegend story for donut charts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CustomLegend story demonstrates the render prop API for fully custom legend layouts — a pattern not covered by the standardized WithLegend/WithCompositionLegend stories. --- .../pie-chart/stories/donut.stories.tsx | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx index bf7233d8a90c..cb06a2e223de 100644 --- a/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx +++ b/projects/js-packages/charts/src/charts/pie-chart/stories/donut.stories.tsx @@ -1,3 +1,10 @@ +/* eslint-disable @wordpress/no-unsafe-wp-apis */ +import { + __experimentalText as WPText, + __experimentalHStack as HStack, +} from '@wordpress/components'; +import { Fragment } from 'react'; +import { BaseLegendItem } from '../../../components/legend/types'; import { chartDecorator, sharedChartArgTypes, @@ -7,9 +14,10 @@ import { legendArgTypes, themeArgTypes, } from '../../../stories'; +import { customerRevenueData, customerRevenueLegendData } from '../../../stories/sample-data'; import { Group } from '../../../visx/group'; import { Text } from '../../../visx/text'; -import { PieChart } from '../../pie-chart'; +import { PieChart, PieChartUnresponsive } from '../../pie-chart'; import type { Meta, StoryObj } from '@storybook/react'; type StoryArgs = ChartStoryArgs< React.ComponentProps< typeof PieChart > >; @@ -254,3 +262,84 @@ export const WithCompositionLegend: Story = { }, }, }; + +const CustomPieLegend = ( { + chartItems, + items, + withComparison, +}: { + chartItems: BaseLegendItem[]; + items: { label: string; value: number; formattedValue: string; comparison: string }[]; + withComparison: boolean; +} ) => ( +
+ { items.map( ( item, index ) => { + const { color } = chartItems[ index ]; + + return ( + + +
+ { item.label } + + + { item.formattedValue } + + + { withComparison && item.comparison } + + + ); + } ) } +
+); + +export const CustomLegend: Story = { + render: args => ( + + ( + + ) } + /> + + ), + args: { + ...Default.args, + data: customerRevenueData, + showLabels: false, + thickness: 0.3, + cornerScale: 0.03, + gapScale: 0.01, + size: 164, + withComparison: true, + withTooltips: false, + containerHeight: '300px', + }, + parameters: { + docs: { + description: { + story: 'Demonstrates how to customize the legend using the render prop.', + }, + }, + }, +}; From e7352b52a4c99ff61f6be7efba703e42fc73adbd Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:38:25 +1300 Subject: [PATCH 5/5] fix(charts): Add missing args and remove redundant orientation defaults Add explicit args to BarChart and LineChart WithCompositionLegend stories so Storybook Controls panel shows initialized values, matching the pattern used by all other chart composition stories. Remove redundant orientation="horizontal" from legend stories and docs Source blocks since horizontal is already the default. --- .../src/charts/bar-chart/stories/index.stories.tsx | 3 +++ .../src/charts/line-chart/stories/index.stories.tsx | 3 +++ .../src/components/legend/stories/index.docs.mdx | 11 +++-------- .../src/components/legend/stories/index.stories.tsx | 8 +++----- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx index 4051720d3a10..b6044c96dda4 100644 --- a/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/bar-chart/stories/index.stories.tsx @@ -268,6 +268,9 @@ export const WithCompositionLegend: StoryObj< typeof BarChart > = { ); }, + args: { + ...Default.args, + }, parameters: { docs: { description: { diff --git a/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx b/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx index f59fcba9dcbf..1503e39982f0 100644 --- a/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/charts/line-chart/stories/index.stories.tsx @@ -171,6 +171,9 @@ export const WithCompositionLegend: StoryObj< typeof LineChart > = { ); }, + args: { + ...Default.args, + }, parameters: { docs: { description: { diff --git a/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx b/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx index ef63747c939f..de9b83ac4341 100644 --- a/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx +++ b/projects/js-packages/charts/src/components/legend/stories/index.docs.mdx @@ -20,7 +20,7 @@ The Legend component offers multiple ways to display chart legends, from simple // Composition API (recommended) - + // Standalone usage with manual data @@ -30,7 +30,6 @@ The Legend component offers multiple ways to display chart legends, from simple { label: 'Series 1', value: '25%', color: '#3858E9' }, { label: 'Series 2', value: '35%', color: '#80C8FF' }, ] } - orientation="horizontal" />` } /> @@ -105,7 +104,7 @@ The recommended way to add legends to charts is the composition API. Use the cha code={ `import { LineChart } from '@automattic/charts'; - + ` } /> @@ -118,7 +117,7 @@ This works with all chart types that support legends: code={ `import { BarChart } from '@automattic/charts'; - + ` } /> @@ -150,7 +149,6 @@ For decoupled layouts such as dashboards, the Legend component can retrieve data {/* Standalone legend that automatically gets data from chart context */}
` } @@ -216,7 +214,6 @@ Interactive legends also work with standalone Legend components. Set `legend.int ` } @@ -273,7 +270,6 @@ The Legend component provides comprehensive text overflow handling for long labe language="tsx" code={ `` } @@ -289,7 +285,6 @@ By default, legends use rectangular shapes, but you can customize the glyph shap language="tsx" code={ `` } /> diff --git a/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx b/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx index 26da6d4a58a2..8a18f61d9fb9 100644 --- a/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx +++ b/projects/js-packages/charts/src/components/legend/stories/index.stories.tsx @@ -116,7 +116,7 @@ export const WithLineChart: Story = { withLegendGlyph={ false } chartId="legend-line-chart" > - +
), }; @@ -125,7 +125,7 @@ export const WithLineChart: Story = { export const WithBarChart: Story = { render: () => ( - + ), }; @@ -145,7 +145,7 @@ const StandaloneLegendWithChartIdComponent = () => { withLegendGlyph={ false } /> { /* Standalone legend that automatically gets data from chart context */ } - + ); }; @@ -300,7 +300,6 @@ export const AlignmentOptions: Story = { { label: 'Series 2', value: '35%', color: '#80C8FF' }, { label: 'Series 3', value: '40%', color: '#44B556' }, ], - orientation: 'horizontal', alignment: 'start', }, }; @@ -376,7 +375,6 @@ export const CustomShape: Story = { { label: 'Desktop', value: '65%', color: '#3858E9' }, { label: 'Mobile', value: '35%', color: '#80C8FF' }, ], - orientation: 'horizontal', shape: 'circle', }, };