Premium Analytics: note adjustments in the Earnings History widget - #52526
Conversation
When the earnings payload carries adjustment rows, the widget renders an "Includes N adjustments" link above its footer, into the Adjustments history tab of the Earnings report. Sites without adjustments render exactly as before. The amounts and notes stay on the report. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! Jetpack plugin: The Jetpack plugin has different release cadences depending on the platform:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Wpcomsh plugin:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Premium Analytics plugin: No scheduled milestone found for this plugin. If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. |
Code Coverage SummaryCoverage changed in 1 file.
|
Second child of the footer, so View all keeps its place and the link takes the far end only on sites that have adjustments. The tile height no longer changes for them either. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s-earnings-history-adjustments-line # Conflicts: # projects/packages/premium-analytics/widgets/wordads-earnings-history/stories/wordads-earnings-history-widget.stories.tsx
Per Eder's design pass: the footer link is an "N adjustments" badge, without "Includes", so it cannot crowd View all in a narrow tile. ReportLink gains a children slot for it and drops its hover underline there. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
b415768 to
8dcc8a3
Compare
The link with content is an inline-flex box, so the badge inside it takes its line height plus padding, matching the status badges. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Nikschavan
left a comment
There was a problem hiding this comment.
Thank you, the changes look good. I left two comments inline: one on the badge link's accessible name, one on the singular test case.
What I checked: the Default and NoAdjustments stories from this branch in Storybook, the inset focus ring on the badge from the keyboard, and the footer at a 260px tile to confirm View all and the badge stay on one row.
| Badge in the footer | Without adjustments |
|---|---|
![]() |
![]() |
| Keyboard focus on the badge | 260px tile |
|---|---|
![]() |
![]() |
| <ReportLink | ||
| report="earnings" | ||
| section="adjustments" | ||
| ariaLabel={ __( 'View adjustments history', 'jetpack-premium-analytics-pkg' ) } |
There was a problem hiding this comment.
The aria-label replaces the badge text as the link's accessible name, so a screen reader announces "View adjustments history" and never the count, which is the one thing this badge adds over View all (render.tsx#L77). Voice control has the mirror problem: the visible "2 adjustments" is not part of the name, so speaking it does not activate the link (WCAG 2.5.3). A label built from the same _n() string, such as "2 adjustments, view adjustments history", would keep both.
There was a problem hiding this comment.
Good catch on both counts. The label is now built from the same _n() string as the badge, so the accessible name is "2 adjustments, view adjustments history" and the visible count is part of it.
| await expect( screen.findByText( 'July 2026' ) ).resolves.toBeInTheDocument(); | ||
|
|
||
| const link = screen.getByRole( 'link', { name: 'View adjustments history' } ); | ||
| expect( link ).toHaveTextContent( label ); |
There was a problem hiding this comment.
toHaveTextContent( label ) matches a substring, so the 1-row case still passes when the singular form is lost: with both _n() forms set to %d adjustments the badge reads "1 adjustments", which contains "1 adjustment", and the suite stays green. Only the 2-row case catches a swap. An exact match such as getByText( label ) would make the singular row fail for its own reason.
There was a problem hiding this comment.
Switched to an exact match inside the link: within( link ).getByText( label ). The singular row now fails on its own if the forms are swapped.
| section="adjustments" | ||
| ariaLabel={ __( 'View adjustments history', 'jetpack-premium-analytics-pkg' ) } | ||
| > | ||
| <Badge intent="high"> |
There was a problem hiding this comment.
I wonder if Badge should be the link itself? We have to remove the link styling to make it fit, and @wordpress/ui describes Badge as a status label, not something you click.
If we want it to look like a chip, LinkButton may be a better fit. Right now the widget draws its own footer, but later, we will replace this with native widget actions the host draws it (WordPress/gutenberg#81740) and only uses Link or LinkButton. cc @retrofox
There was a problem hiding this comment.
Fair point: nothing in the monorepo puts a Badge inside a link today, so this is a first. I tried a plain Adjustments link with a count badge beside it, but it reads as two things and drifts from Eder's single-chip design for this line; LinkButton keeps the shape but loses the intent colour.
I'd like to ship this as designed and settle the component question in a follow-up with Eder and @retrofox. The change is contained (ReportLink only gained a children slot), so swapping to Link or LinkButton later is a small local change. I'll open the follow-up and link it here.
The aria-label replaced the badge text as the link's accessible name, so screen readers never heard the count and voice control could not match the visible "2 adjustments". Build the label from the same _n() string. The test now matches the badge text exactly, so the singular row fails on its own if the plural forms are swapped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>




Fixes WOOA7S-2155
Proposed changes
Adjustments are reconciliation rows: a transfer or a support compensation moves the All-time balance, and the
adjustmentbucket is the only thing that explains why the balance does not equal the sum of the WordAds months. Since #52420 removed the Adjustments History widget, the Earnings report's Adjustments tab (#52437) is their only home, and nothing on the Ads tab points there.adjustmentrow, the Earnings History widget renders an N adjustments badge at the far end of its footer, opposite View all, linking into/reports/earnings?section=adjustments. The count is the number of adjustment rows, so it implies no sign; the amounts themselves stay on the report.notesis never read. It carries other blog IDs and, occasionally, Zendesk URLs.Defaultshows the line; a newNoAdjustmentsstory shows the unchanged widget.From Eder's design pass on the Slack thread: the adjustments link is a badge, without "Includes", so it cannot crowd View all in a narrow tile.
ReportLinkgained achildrenslot for it and drops its hover underline there. The other half of that pass, badges for the widget's status column, is #52565.The card's own placement, a line between the list and the footer, was tried first and dropped: it cost the list a row and read as a stray line.
Related product discussion/links
Does this pull request change what data or activity we track or use?
No.
Testing instructions
Use a site with adjustment rows, or mock
proxy/v1.1/wordads/earningswith at least one row inadjustment. On the local Docker site thezz-tmp-pa-wordads-mock.phpmu-plugin returns two.adjustmentbucket (wp option update jpa_mock_wordads_only 1with the mu-plugin). Confirm the widget renders exactly as before: View all alone in the footer.jp test js packages/premium-analyticspasses.🤖 Generated with Claude Code