Skip to content

Conversation

adamwoodnz
Copy link
Contributor

@adamwoodnz adamwoodnz commented Jun 30, 2025

Fixes CHARTS-47: Line Chart: Custom annotations

Proposed changes:

Adds support for custom annotations with interactivity

  • Optional renderLabel prop per annotation item which renders custom HTML instead of a basic label
  • Optional renderLabelPopover prop per annotation which turns the label into a button and will open a popup with custom HTML

Screenshots

Custom vertical line with popover Custom circle with popover
Screenshot 2025-07-10 at 10 53 28 AM Screenshot 2025-07-10 at 10 53 37 AM

Notes

Includes a breaking change to the annotations API, from an annotations prop to a compound component pattern, with declarative nested LineChart.Annotation components.

Due to a known issue with positioning within foreignObject elements in Safari, the popovers are positioned in the center of the viewport rather than next to the annotation. This can be improved in a further iteration.

The annotations are rendered in a separate layer above the tooltips, so they are focused individually for now. I think in a further iteration we should add handling similar to what we have for tooltips, so that the annotations overlay is one stop in the tabindex and annotations are focused within that, using arrow keys.

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

pcO4xN-2zR-p2

Does this pull request change what data or activity we track or use?

No

Testing instructions:

Copy link
Contributor

github-actions bot commented Jun 30, 2025

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add a "[Type]" label (Bug, Enhancement, Janitorial, Task).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

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:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@github-actions github-actions bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Jun 30, 2025
@adamwoodnz adamwoodnz added [Type] Feature Development of a new feature and removed [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. labels Jun 30, 2025
Copy link

jp-launch-control bot commented Jun 30, 2025

Code Coverage Summary

Coverage changed in 3 files.

File Coverage Δ% Δ Uncovered
projects/js-packages/charts/src/components/line-chart/line-chart-annotation.tsx 82/88 (93.18%) 1.63% 0 💚
projects/js-packages/charts/src/components/line-chart/line-chart.tsx 93/98 (94.90%) 1.00% 0 💚
projects/js-packages/charts/src/components/shared/utils.ts 9/9 (100.00%) 0.00% 0 💚

3 files are newly checked for coverage.

File Coverage
projects/js-packages/charts/src/components/line-chart/line-chart-annotation-label-popover.tsx 16/24 (66.67%) 💚
projects/js-packages/charts/src/components/line-chart/line-chart-context.tsx 5/6 (83.33%) 💚
projects/js-packages/charts/src/components/line-chart/line-chart-annotations-overlay.tsx 46/46 (100.00%) 💚

Full summary · PHP report · JS report

@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch from 0cb5041 to c4bf347 Compare July 1, 2025 00:14
Copy link
Contributor

github-actions bot commented Jul 1, 2025

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the charts-47-line-chart-custom-annotations branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack charts-47-line-chart-custom-annotations
bin/jetpack-downloader test jetpack-mu-wpcom-plugin charts-47-line-chart-custom-annotations

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch 5 times, most recently from 5772d4a to f4ab227 Compare July 7, 2025 23:05
<div className={ styles[ 'line-chart__annotation-label' ] }>
<button
ref={ buttonRef }
{ ...( { popovertarget: popoverId } as ButtonWithPopover ) }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using the popover API for these rather than a modal as it has:

Built-in Accessibility: The popover API automatically handles:

  • Focus management
  • ARIA attributes
  • Keyboard navigation (Escape key)
  • Screen reader announcements

Browser Behavior: Native handling of:

  • Click outside to close
  • Proper z-index stacking
  • Scroll behavior
  • Mobile touch interactions

Browser support is good: https://caniuse.com/mdn-api_htmlelement_popover

height: `${ POPOVER_BUTTON_SIZE }px`,
transform: `translate(${ POPOVER_BUTTON_SIZE / 2 }px, 0)`,
} }
aria-label={ title || 'View details' }
Copy link
Contributor Author

@adamwoodnz adamwoodnz Jul 9, 2025

Choose a reason for hiding this comment

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

I found some other instances where we have static untranslated strings, should we be using @wordpress/i18n?

eg.

import { __ } from '@wordpress/i18n';

...
aria-label={ title ?? __( 'See details', 'automattic-charts' ) }
...

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree - we need these translated for sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adamwoodnz adamwoodnz changed the title Charts 47 line chart custom annotations Line chart - custom annotations Jul 9, 2025
@adamwoodnz adamwoodnz requested a review from Copilot July 9, 2025 05:33
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for fully customizable annotations on the LineChart component, including optional HTML labels and popovers.

  • Introduce renderLabel and renderLabelPopover props and refactor annotation rendering to use HtmlLabel and an external overlay.
  • Add a LineChartAnnotationsOverlay component and expose chart scales/dimensions via forwardRef for accurate positioning.
  • Update tests and Storybook stories to cover the new custom annotation and popover capabilities.

Reviewed Changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
projects/js-packages/charts/src/types.ts Add Popover API attribute type definitions
projects/js-packages/charts/src/components/shared/utils.ts Add isSafari helper
projects/js-packages/charts/src/components/line-chart/line-chart.tsx Refactor to support forwarded ref and external overlay
projects/js-packages/charts/src/components/line-chart/line-chart-annotation.tsx Add renderLabel/renderLabelPopover and HTML labels
projects/js-packages/charts/src/components/line-chart/line-chart-annotations-overlay.tsx New overlay component
projects/js-packages/charts/src/components/line-chart/line-chart-annotation-label-popover.tsx New popover button & positioning logic
projects/js-packages/charts/src/components/line-chart/test/* Update and add tests for custom annotations
projects/js-packages/charts/src/components/line-chart/stories/annotation.stories.tsx Add stories for custom annotations
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)

projects/js-packages/charts/src/components/line-chart/line-chart-annotation.tsx:47

  • [nitpick] The new renderLabel and renderLabelPopover props lack JSDoc comments. Consider adding descriptions for these hooks in LineChartAnnotationProps to clarify their purpose and usage.
	renderLabel?: FC< { title: string; subtitle?: string } >;

projects/js-packages/charts/src/components/line-chart/line-chart-annotation.tsx:162

  • [nitpick] The default vertical anchor was changed from 'middle' to 'start', which may misalign existing annotations. Verify whether this change is intentional or should be reverted to preserve the previous positioning.
		return 'start';

@annacmc
Copy link
Contributor

annacmc commented Jul 9, 2025

Hey @adamwoodnz ! I've been working on a chart context feature that
enables modular legend management, and I'm curious about potential
collaboration opportunities with your annotations work.

Currently, chart context allows legends to be rendered independently from
charts - you can place a <Legend> component anywhere and it reads chart data
from context. This creates a really flexible architecture where multiple charts
can share legends, or legends can be positioned outside chart containers.

I'm wondering if we should explore extending this pattern to annotations as
well. Right now your implementation passes annotations as props directly to the
chart (which works great!), but I'm thinking about whether a context-based
approach might unlock similar modularity:

// Current approach

<LineChart annotations={annotationData} />

// Potential context approach

 <ChartProvider>
   <LineChart />
   <ChartAnnotations>
     <Annotation x="2023-01-01" y={100} label="Launch" />
   </ChartAnnotations>
 </ChartProvider>

This could enable things like shared annotations across multiple charts, or
annotations that respond to context-level events. The main challenge would be
that annotations need real-time access to scales/dimensions (which you've
solved elegantly with the ref pattern), whereas legends work with more static
data.

What are your thoughts? Worth exploring, or do you think the current prop-based
approach better serves the annotation use cases you're targeting?

Copy link
Contributor Author

Yeah I certainly think it's worth exploring, I'll take a look at your PR 👍

@adamwoodnz adamwoodnz requested a review from a team July 10, 2025 03:32
@adamwoodnz adamwoodnz marked this pull request as ready for review July 10, 2025 03:32
Comment on lines 609 to 643
{ /* Render annotations as external overlay to avoid interaction blocking */ }
{ annotations?.length && (
<LineChartAnnotationsOverlay
chartRef={ internalChartRef }
annotations={ annotations }
chartWidth={ width }
chartHeight={ height - ( showLegend ? legendHeight : 0 ) }
/>
) }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The XYChart renders a rect interaction layer over the whole chart which is used for tooltips, etc. If the annotations are rendered within the XYChart then they are not clickable, even with z-index changes. This means we need to render them above and create our own annotations overlay which handles synchronising the chart dimensions and scales for correct positioning of the annotations.

@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch from def84b6 to 3e33514 Compare July 10, 2025 22:59
@adamwoodnz
Copy link
Contributor Author

bugbot run

@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch from 3e33514 to 7176c2d Compare July 11, 2025 01:39
adamwoodnz and others added 21 commits July 16, 2025 14:13
…fying label positioning logic and improving code clarity.
…dering in LineChart. Update renderLabel methods to utilize these new components, enhancing code clarity and maintainability.
…ing proper rendering only when scales are stable.
- fallback to centered position for Safari due to foreign object issues
- add space around popover to allow for hitting viewport boundaries
…for clarity and update import references accordingly.
…mensions. Update tests to ensure proper behavior when annotations are provided, absent, or empty.
@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch from e51b142 to 16dd7d4 Compare July 16, 2025 02:27
Include the breaking change to the annotations API
@adamwoodnz adamwoodnz force-pushed the charts-47-line-chart-custom-annotations branch from 972efef to 6616ff8 Compare July 16, 2025 20:07
@adamwoodnz adamwoodnz merged commit 2cf8757 into trunk Jul 16, 2025
85 checks passed
@adamwoodnz adamwoodnz deleted the charts-47-line-chart-custom-annotations branch July 16, 2025 21:26
@github-actions github-actions bot removed the [Status] Needs Team Review Obsolete. Use Needs Review instead. label Jul 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants