Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
71c036f
premium-analytics: port average-items-per-order widget
nerrad Jun 10, 2026
51bcc3d
premium-analytics: wire the Range editor from the fields package
nerrad Jun 12, 2026
2c13a12
Premium Analytics: address average items widget review feedback
nerrad Jun 13, 2026
f74be68
Premium Analytics: add average items widget story
nerrad Jun 13, 2026
3fd2b9e
Premium Analytics: align average items story sizes
nerrad Jun 13, 2026
5aa81b1
Premium Analytics: fix compact comparison legend wrapping
nerrad Jun 13, 2026
823d865
Premium Analytics: add dashboard-sized average items stories
nerrad Jun 13, 2026
e561ace
Premium Analytics: refine compact legend alignment
nerrad Jun 13, 2026
1445987
Premium Analytics: prevent compact chart legend clipping
nerrad Jun 13, 2026
b36b9e4
Premium Analytics: constrain comparative chart layout
nerrad Jun 13, 2026
ee62a69
Premium Analytics: fix narrow comparison legend clipping
nerrad Jun 13, 2026
e5d6596
Premium Analytics: add global error provider stories
nerrad Jun 13, 2026
2668de0
Premium Analytics: show widget error stories
nerrad Jun 13, 2026
e898276
Premium Analytics: move widget errors into dashboard chrome
nerrad Jun 13, 2026
82b6825
Premium Analytics: stabilize widget error stories
nerrad Jun 16, 2026
c8412a6
Premium Analytics: Remove extracted widget error handling
nerrad Jun 16, 2026
12023b6
Premium Analytics: Fix comparative legend wrapping
nerrad Jun 16, 2026
36dccff
Premium Analytics: Stabilize comparative legend wrapping
nerrad Jun 16, 2026
6228f46
Premium Analytics: Consolidate dashboard widget stories
nerrad Jun 16, 2026
79a97e9
Premium Analytics: Use WordPress widget packages in stories
nerrad Jun 22, 2026
11af3a3
Premium Analytics: Clean widget port config
nerrad Jun 22, 2026
9479027
Premium Analytics: Refine average items Storybook stories
nerrad Jun 23, 2026
428a124
Premium Analytics: Use datetime presets in story
nerrad Jun 24, 2026
3c87144
Premium Analytics: Use Stack for comparative chart layout
nerrad Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added

Add a Premium Analytics Average items per order widget story.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added

Port the Average items per order dashboard widget from next-woocommerce-analytics, composed from the widgets-toolkit and data packages.
17 changes: 17 additions & 0 deletions projects/packages/premium-analytics/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,22 @@ export default defineConfig(
'@wordpress/no-unsafe-wp-apis': 'off',
'@wordpress/no-unknown-ds-tokens': 'off',
},
},
{
// Ported widget code keeps the upstream next-woocommerce-analytics
// JSDoc style, and imports internal `@jetpack-premium-analytics/*`
// link: packages whose deps are declared on the parent manifest.
files: [ 'widgets/**' ],
rules: {
'import/order': 'off',
'jsdoc/require-description': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/check-indentation': 'off',
'jsdoc/require-param': 'off',
'jsdoc/require-jsdoc': 'off',
'jsdoc/escape-inline-tags': 'off',
'import/no-extraneous-dependencies': 'off',
},
}
);
2 changes: 2 additions & 0 deletions projects/packages/premium-analytics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@
"@jetpack-premium-analytics/datetime": "link:packages/datetime",
"@jetpack-premium-analytics/fields": "link:packages/fields",
"@jetpack-premium-analytics/formatters": "link:packages/formatters",
"@jetpack-premium-analytics/icons": "link:packages/icons",
"@jetpack-premium-analytics/routing": "link:packages/routing",
"@jetpack-premium-analytics/site-sync": "link:packages/site-sync",
"@jetpack-premium-analytics/ui": "link:packages/ui",
"@jetpack-premium-analytics/widgets-toolkit": "link:packages/widgets-toolkit",
"@tanstack/react-query": "5.90.8",
"@wordpress/admin-ui": "2.3.1",
"@wordpress/api-fetch": "7.48.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
.chart {
height: 100%;
min-height: 0;
flex: 1 1 auto;
display: flex;
flex-direction: column;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should replace the regular div with the chart class with a Stack component. It's acting like a part of the component layout.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually, I'm not sure what the purpose of these styles is. I guess we're trying to force the widget to take the whole height, but I thought that height: 100% should be enough?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see, it's needed to stretch its immediate children. Below:

	> div {
		flex: 1 1 auto;
		min-height: 0;
	}

Using this > div class doesn't look good .

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good points, I've replaced with Stack, but it looks like here are still some style tweaks needed. This particular component is in the widgets-toolkit package and is one of the ones that should be migrated to @automattic/charts as a part of the composite chart components. So I think this can help inform that eventual migration (and further SCSS edits can happen as a part of that).


> div {
flex: 1 1 auto;
min-height: 0;
}

.chartContent {
height: 100%;
min-height: 0;
}

.legend {
flex: 0 0 auto;
height: var(--wpds-typography-line-height-lg);
width: 100%;
height: auto;
min-height: var(--wpds-typography-line-height-lg);
flex-wrap: nowrap;
align-content: center;
align-items: center;
justify-content: center;
flex-wrap: wrap;
row-gap: var(--wpds-dimension-gap-xs) !important;
}

.legendItem {
min-width: 0;
max-width: 100%;
flex: 0 1 auto;
gap: var(--wpds-dimension-gap-sm);
justify-content: flex-start;
padding: var(--wpds-dimension-padding-xs) var(--wpds-dimension-padding-sm); // 4px 6px->8px
}

.legendLabel {
// font-size and color come from chartTheme.legendLabelStyles
min-width: 0;
flex: 1 1 0 !important; // Override the 0 0 auto default value
flex: 0 1 auto !important; // Override the 0 0 auto default value
text-align: start;

span {
display: block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,35 +317,37 @@ export function ComparativeLineChart( {
] );

return (
<LineChart
className={ clsx( styles.chart, className ) }
data={ styledSeries }
options={ chartOptions }
margin={ percentageMargin ?? emptyChartProps.margin ?? DEFAULT_MARGIN }
maxWidth={ maxWidth }
resizeDebounceTime={ RESIZE_DEBOUNCE_MS }
withLegendGlyph={ false }
showLegend={ false }
curveType="monotone"
withGradientFill
withTooltips={ !! renderTooltip && ! isEmptyData }
renderTooltip={ renderTooltip }
>
<LineChart.Legend
shape="line"
className={ styles.legend }
itemClassName={ styles.legendItem }
itemStyles={ {
margin: 0,
} }
labelClassName={ styles.legendLabel }
labelStyles={ {
maxWidth: '100%',
textOverflow: 'ellipsis',
margin: 0,
} }
shapeStyles={ { margin: 0 } }
/>
</LineChart>
<div className={ clsx( styles.chart, className ) }>
<LineChart
className={ styles.chartContent }
data={ styledSeries }
options={ chartOptions }
margin={ percentageMargin ?? emptyChartProps.margin ?? DEFAULT_MARGIN }
maxWidth={ maxWidth }
resizeDebounceTime={ RESIZE_DEBOUNCE_MS }
withLegendGlyph={ false }
showLegend={ false }
curveType="monotone"
withGradientFill
withTooltips={ !! renderTooltip && ! isEmptyData }
renderTooltip={ renderTooltip }
>
<LineChart.Legend
shape="line"
className={ styles.legend }
itemClassName={ styles.legendItem }
itemStyles={ {
margin: 0,
} }
labelClassName={ styles.legendLabel }
labelStyles={ {
maxWidth: '100%',
textOverflow: 'ellipsis',
margin: 0,
} }
shapeStyles={ { margin: 0 } }
/>
</LineChart>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@automattic/jetpack-premium-analytics-widget-average-items-per-order",
"version": "0.1.0-alpha",
"private": true,
"type": "module",
"dependencies": {
"@jetpack-premium-analytics/widgets-toolkit": "link:../../packages/widgets-toolkit",
"@wordpress/i18n": "^6.9.0",
"@wordpress/icons": "^13.0.0",
"@wordpress/ui": "0.13.0",
"react": "18.3.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
OrderMetricWidget,
WidgetRoot,
type ReportParamsFieldAttributes,
} from '@jetpack-premium-analytics/widgets-toolkit';

type AverageItemsPerOrderRenderProps = {
attributes?: Partial< ReportParamsFieldAttributes >;
};

/**
* Average items per order widget.
*
* Thin composition over the widgets-toolkit: WidgetRoot provides the query
* client, chart theme, and resolved report params; OrderMetricWidget fetches
* the orders report and renders the avg_items metric with a comparison delta
* and sparkline.
*/
export default function AverageItemsPerOrderRender( {
attributes,
}: AverageItemsPerOrderRenderProps ) {
return (
<WidgetRoot attributes={ attributes } options={ { from: '/' } }>
<OrderMetricWidget metricKey="avg_items" />
</WidgetRoot>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { getDefaultQueryParams } from '@jetpack-premium-analytics/data';
import {
DEFAULT_WIDGET_DASHBOARD_STORY_ARGS,
WidgetDashboardWithWidget as WidgetDashboardWithWidgetStory,
widgetDashboardWithWidgetArgTypes,
type WidgetDashboardWithWidgetControls,
} from '../../stories/widget-dashboard-with-widget';
import { registerReportMocks } from '../../../packages/widgets-toolkit/src/stories/mocks/register-report-mocks';
import AverageItemsPerOrderRender from '../render';
import widgetDefinition from '../widget';
import type { Meta, StoryObj } from '@storybook/react';
import type { WidgetRenderProps } from '@wordpress/widget-primitives';
import type { ComponentType } from 'react';

registerReportMocks();

const AVERAGE_ITEMS_RENDER_MODULE = 'storybook/average-items-per-order';

interface AverageItemsPerOrderDashboardStoryProps extends WidgetDashboardWithWidgetControls {
withComparison: boolean;
}

function AverageItemsPerOrderDashboardStory( {
withComparison,
...dashboardStoryArgs
}: AverageItemsPerOrderDashboardStoryProps ) {
return (
<WidgetDashboardWithWidgetStory
Comment thread
nerrad marked this conversation as resolved.
{ ...dashboardStoryArgs }
widgetType={ widgetDefinition }
renderModule={ AVERAGE_ITEMS_RENDER_MODULE }
renderComponent={
AverageItemsPerOrderRender as ComponentType< WidgetRenderProps< unknown > >
}
attributes={ {
reportParams: getDefaultQueryParams( withComparison ),
} }
/>
);
}

const meta = {
title: 'Packages/Premium Analytics/Widgets/AverageItemsPerOrder',
component: AverageItemsPerOrderDashboardStory,
tags: [ 'autodocs' ],
args: {
...DEFAULT_WIDGET_DASHBOARD_STORY_ARGS,
withComparison: true,
},
argTypes: {
...widgetDashboardWithWidgetArgTypes,
withComparison: {
control: 'boolean',
},
},
parameters: {
docs: {
description: {
component:
'Dashboard widget that displays the average number of items per order with an optional comparison period and sparkline.',
},
},
},
} satisfies Meta< typeof AverageItemsPerOrderDashboardStory >;

export default meta;

type Story = StoryObj< typeof meta >;

export const WidgetDashboardWithWidget: Story = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "jpa/average-items-per-order",
"title": "Average items per order",
"description": "Show the average number of products per order over a set period of time.",
"category": "orders"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { chartBar } from '@wordpress/icons';

/**
* Widget type definition.
*
* Ported from `woocommerce-analytics/average-items-per-order` in
* woocommerce/woocommerce-analytics (next-woocommerce-analytics).
*
* Report params intentionally come from the analytics dashboard's global
* date-range state for now. Adding widget-level overrides needs a host-level
* control registry so analytics dashboards can hide the field while other
* dashboards can opt in.
*/
export default {
name: 'jpa/average-items-per-order',
title: __( 'Average items per order', 'jetpack-premium-analytics' ),
description: __(
'Show the average number of products per order over a set period of time.',
'jetpack-premium-analytics'
),
icon: chartBar,
};
Loading
Loading