Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
efc60a5
WOOA7S-2294: Premium Analytics: Add Build URL to empty UTM widget (#5…
Nikschavan Oct 13, 2026
5905bde
Connection: Transfer ownership without leaving the site (#53359)
fgiannar Oct 13, 2026
0d3df8b
My Jetpack: Show the highest-priority global notice first (#53400)
xavier-lc Oct 13, 2026
dca51f1
Connection: Build connectors card as a bundled ES module (#53179)
coder-karen Oct 13, 2026
2ceede9
WooCommerce Stats: move the columns widgets into the package (#53477)
retrofox Oct 13, 2026
9da92df
Podcast: load the dashboard's JavaScript translations (#53042)
emilyaudela Oct 13, 2026
d9f7bad
jetpack-mu-wpcom: Sync React 19 incompatible plugins with Gutenberg (…
jsnajdr Oct 13, 2026
ce8a689
phan: Update custom stubs (#53517)
matticbot Oct 13, 2026
e25a2a2
Shortcodes: Use apply_shortcodes() instead of do_shortcode() (#53543)
daefery Oct 13, 2026
dfe5a24
Themes: share one WordPress.com themes data layer between the Marketp…
dsas Oct 13, 2026
5620ebd
PayPal Payment Buttons: Remove the product image field from the edito…
millerf Oct 13, 2026
0c737b9
Plugins: turn the Marketplace tab on, and let it work on the Simple s…
rcrdortiz Oct 13, 2026
ac4666e
Tools: Update release tool changelog logic (#53512)
tbradsha Oct 13, 2026
fe0258c
Backup: flip the folder chevrons and back arrows in right-to-left lan…
CGastrell Oct 13, 2026
bb1fb5f
Comments: Accept a stale nonce from the site's own page (#53532)
arcangelini Oct 13, 2026
4c45f77
Comments: Keep the sign-in when a reader goes back and reposts (#53531)
arcangelini Oct 13, 2026
a6793cb
Premium Analytics: add a Locations widget kind over the chart pieces …
retrofox Oct 13, 2026
9b2934d
wpcomsh: Keep Activity Log module on for WoA sites (#53546)
jboland88 Oct 13, 2026
1045c61
Backup: make dates, times and sizes follow the locale (#53486)
CGastrell Oct 13, 2026
a03824a
Post by Email: Clean up the per-user local copy of the address (#53440)
kraftbj Oct 13, 2026
4db3eaf
Protect Dashboard: Address Scan feedback (#53439)
enejb Oct 13, 2026
4ee971f
Comments: Keep the form nonce out of the page HTML (#53547)
arcangelini Oct 13, 2026
94a7527
Boost: Fix oversized "Learn what to do" link in the Critical CSS fail…
alinclamba Oct 13, 2026
7c49b47
Premium Analytics: expose the Locations widget kind through the SDK (…
retrofox Oct 13, 2026
5f27bbf
Newsletter: link to the email design screen from the email previewer …
allilevine Oct 13, 2026
c3ecc74
Newsletter: render the logged-out version of a post for ActivityPub (…
jeherve Oct 13, 2026
057e60e
wpcomsh: Stop forcing the Activity Log module on (#53559)
kraftbj Oct 13, 2026
3c232b5
JSON API: Save the allow list posted to the site settings endpoint (#…
kraftbj Oct 13, 2026
956e58c
Protect: Let the firewall and Account protection endpoints accept the…
kraftbj Oct 13, 2026
b105552
CLI: Read the current allow list in wp jetpack protect allow (#53315)
kraftbj Oct 13, 2026
2e9fbfc
Backup: make the Restore to this point focus ring visible (#53416)
dhasilva Oct 13, 2026
c506a5a
Jetpack Settings: retire the jetpack-settings-wp-build flag and the w…
dhasilva Oct 13, 2026
9c5ba7c
Monitor: Store the downtime email setting per user (#53384)
kraftbj Oct 13, 2026
fb8a2a6
Protect Dashboard: Add the Monitor section (#53194)
enejb Oct 13, 2026
b41f94d
WAF: Preserve approved login attempts during math fallback (#50681)
DevinWalker Oct 13, 2026
16f2d99
Backup: survive failed status polls, and only say a restore didn't st…
CGastrell Oct 13, 2026
0420988
Use `apply_shortcodes()` instead of `do_shortcode()` (#53552)
tbradsha Oct 13, 2026
7a7cd5a
Blogroll block: Fix PHP warnings (#53561)
tbradsha Oct 13, 2026
a294731
YouTube: fix livestream links showing no thumbnail or embed (#53564)
robertbpugh Oct 13, 2026
e731b33
Newsletter: make the blog sticker the email design screen's switch on…
allilevine Oct 13, 2026
6de1381
Charts: Give every chart an accessible name (#53516)
adamwoodnz Oct 13, 2026
4a85803
Comments: Leave theme-built comment forms alone (#53550)
arcangelini Oct 13, 2026
9361162
Comments: Show X, Bluesky, and Reddit embeds as cards, and TikTok as …
arcangelini Oct 13, 2026
8c86d6c
SEO: Make the Canonical URLs switch work on WordPress.com Simple (#53…
haqadn Oct 13, 2026
05726fc
Map block: preserve saved locations during editor initialization (#53…
glendaviesnz Oct 13, 2026
9bc2aeb
VideoPress: keep playlist links to this site's video pages in the tab…
heydemoura Oct 13, 2026
997ef4d
SEO Tools: Stop a post's noindex setting leaking onto the homepage an…
haqadn Oct 13, 2026
bc848f8
PayPal Payment Buttons: Collect the shipping address without a shippi…
tx2pnw Oct 14, 2026
a1ebaaa
PayPal Payment Buttons: gray the button until the link is created (#5…
tx2pnw Oct 14, 2026
baff5bf
Jetpack AI: Send the editor and Settings links to the Jetpack AI Hub …
ariskataoka Oct 14, 2026
0cf5fca
Premium Analytics: Add All time to the report date menu (#53275)
chihsuan Oct 14, 2026
00427c8
Premium Analytics: Add an E2E test for dates across viewer and site t…
chihsuan Oct 14, 2026
356b09d
Premium Analytics: Trim AGENTS.md and document the rebuild loop (#53523)
chihsuan Oct 14, 2026
317ba38
WOOA7S-2309: Premium Analytics: Show the search icon in every widget …
Nikschavan Oct 14, 2026
2610609
WOOA7S-2038: Premium Analytics: Show a notice when the site nears or …
Nikschavan Oct 14, 2026
ef75856
WOOA7S-2295: VideoPress: Offer upload when Top videos has no videos (…
Nikschavan Oct 14, 2026
d324c57
Merge remote-tracking branch 'origin/trunk' into update/wordpress-ui-…
Nikschavan Oct 14, 2026
189d5dc
Rename the @wordpress/ui 0.24 components that trunk added after the l…
Nikschavan Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 16 additions & 2 deletions .phan/stubs/phpunit-stubs.php

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.

This file is automatically generated and should not be edited directly. See the comment at the top of the file for details.

If you have any questions, ping @Automattic/jetpack-monorepo.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Stubs automatically generated from PHPUnit 12.5.38
* Stubs automatically generated from PHPUnit 12.5.39
* using the definition file `tools/stubs/phpunit-stub-defs.php` in the Jetpack monorepo.
*
* Do not edit this directly! Run tools/stubs/update-stubs.sh to regenerate it.
Expand Down Expand Up @@ -13309,7 +13309,7 @@ public function matchesName(string $methodName): bool
final class Parameters implements \PHPUnit\Framework\MockObject\Rule\ParametersRule
{
/**
* @param array<mixed> $parameters
* @param array<int|string, mixed> $parameters
* @throws \PHPUnit\Framework\Exception
*/
public function __construct(array $parameters)
Expand Down Expand Up @@ -25730,6 +25730,20 @@ public function download(string $url): false|string
final class PhpProcessException extends \RuntimeException implements \PHPUnit\Util\Exception
{
}
/**
* @no-named-arguments
* @internal
*/
final class ExtensionSettings
{
/**
* @param \Closure(): list<string> $parameters
* @return list<non-empty-string>
*/
public static function forChildProcess(\Closure $parameters): array
{
}
}
/**
* @immutable
* @no-named-arguments
Expand Down
2 changes: 1 addition & 1 deletion .phan/stubs/woocommerce-internal-stubs.php

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.

This file is automatically generated and should not be edited directly. See the comment at the top of the file for details.

If you have any questions, ping @Automattic/jetpack-monorepo.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Stubs automatically generated from WooCommerce 11.2.0
* Stubs automatically generated from WooCommerce 11.2.1
* using the definition file `tools/stubs/woocommerce-internal-stub-defs.php` in the Jetpack monorepo.
*
* Do not edit this directly! Run tools/stubs/update-stubs.sh to regenerate it.
Expand Down
2 changes: 1 addition & 1 deletion .phan/stubs/woocommerce-payments-stubs.php

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.

This file is automatically generated and should not be edited directly. See the comment at the top of the file for details.

If you have any questions, ping @Automattic/jetpack-monorepo.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Stubs automatically generated from WooPayments 11.1.0
* Stubs automatically generated from WooPayments 11.2.0
* using the definition file `tools/stubs/woocommerce-payments-stub-defs.php` in the Jetpack monorepo.
*
* Do not edit this directly! Run tools/stubs/update-stubs.sh to regenerate it.
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

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

4 changes: 4 additions & 0 deletions projects/js-packages/api/changelog/add-cnx-ownership-transfer
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Add methods to list connection owner candidates and set a new connection owner.
12 changes: 12 additions & 0 deletions projects/js-packages/api/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ function JetpackRestApiClient( root, nonce ) {
.then( parseJsonResponse );
},

fetchConnectionOwnerCandidates: () =>
getRequest( `${ apiRoot }jetpack/v4/connection/owner/candidates`, getParams )
.then( checkStatus )
.then( parseJsonResponse ),

setConnectionOwner: ownerId =>
postRequest( `${ apiRoot }jetpack/v4/connection/owner`, postParams, {
body: JSON.stringify( { owner: ownerId } ),
} )
.then( checkStatus )
.then( parseJsonResponse ),

reconnect: () =>
postRequest( `${ apiRoot }jetpack/v4/connection/reconnect`, postParams )
.then( checkStatus )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Give the geo, leaderboard, conversion funnel and bar list charts an accessible name, and accept `ariaLabel` on every chart except Sparkline.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Stacked-by-default area chart component with responsive behaviour.
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| `data` | `SeriesData[]` | - | **Required.** Array of data series to display |
| `ariaLabel` | `string` | `'Area chart'` | Accessible name of the chart. Name it after what it shows; give each chart on a page a different name. |
| `ariaLabel` | `string` | `'Area chart'` | Accessible name. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names). |
| `width` | `number?` | responsive | Chart width in pixels |
| `height` | `number?` | responsive | Chart height in pixels |
| `aspectRatio` | `number` | - | Height-to-width ratio (e.g. `0.4`) for responsive charts; the chart is contained within its parent on both axes. Used when `width`/`height` are omitted. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ The Area Chart supports an optional entry animation:

## Accessibility

- Chart container has `role="application"` and an `aria-label` of `"Area chart"`, so screen readers pass arrow keys through to the chart's point navigation.
- Set `ariaLabel` to name the chart after what it shows, so a screen reader user with several charts on a page can tell them apart.
- Chart container has `role="application"`, so screen readers pass arrow keys through to the chart's point navigation.
- Set `ariaLabel` to name the chart. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names).
- Tab to focus the chart; arrow keys navigate data points; tooltips are announced to screen readers.
- **Escape**: Close a keyboard-opened tooltip and return focus to the chart
- All series colors can be overridden through the palette custom properties; do not rely on color alone to distinguish series.
Original file line number Diff line number Diff line change
Expand Up @@ -785,14 +785,6 @@ describe( 'AreaChart', () => {
const chart = screen.getByRole( 'application', { name: /area chart/i } );
expect( chart ).toHaveAttribute( 'tabIndex', '0' );
expect( chart ).toHaveAttribute( 'aria-label', 'Area chart' );
} );

test.each( [
[ undefined, 'Area chart' ],
[ 'Views over time', 'Views over time' ],
] )( 'names the chart container from ariaLabel %p', ( ariaLabel, name ) => {
renderWithProvider( { ariaLabel } );
expect( screen.getByRole( 'application', { name } ) ).toBeInTheDocument();
expect( screen.queryByLabelText( 'XYChart' ) ).not.toBeInTheDocument();
} );
} );
Expand Down
2 changes: 0 additions & 2 deletions projects/js-packages/charts/src/charts/area-chart/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import type { CurveType } from '../line-chart/types';
import type { ReactNode } from 'react';

export interface AreaChartProps extends BaseChartProps< SeriesData[] >, SeriesVisibilityProps {
/** Accessible name of the chart. Defaults to a localized "Area chart". */
ariaLabel?: string;
/**
* Legend configuration. Supports `collapseGroups` on top of the shared options.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Main chart component with responsive behavior by default.
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| `data` | `SeriesData[]` | - | **Required.** Array of data series to display |
| `ariaLabel` | `string` | `'Bar chart'` | Accessible name of the chart. Name it after what it shows; give each chart on a page a different name. |
| `ariaLabel` | `string` | `'Bar chart'` | Accessible name. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names). |
| `chartId` | `string` | auto-generated | Optional unique identifier for the chart |
| `width` | `number` | responsive | Chart width in pixels |
| `height` | `number` | `400` | Chart height in pixels |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ See [Keyboard Navigation](#keyboard-navigation) for supported keys and focus beh
### Screen Reader Support

- Chart container has `role="application"`, so screen readers pass arrow keys through to the chart's point navigation.
- Set `ariaLabel` to name the chart after what it shows, so a screen reader user with several charts on a page can tell them apart.
- Set `ariaLabel` to name the chart. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names).
- Individual bars are navigable and announced with their values
- Interactive elements have appropriate ARIA attributes
- Color information is supplemented with patterns when `withPatterns` is enabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1685,14 +1685,6 @@ describe( 'BarChart', () => {
expect( chart ).toHaveAttribute( 'tabIndex', '0' );
expect( chart ).toHaveAttribute( 'role', 'application' );
expect( chart ).toHaveAttribute( 'aria-label', 'Bar chart' );
} );

test.each( [
[ undefined, 'Bar chart' ],
[ 'Views over time', 'Views over time' ],
] )( 'names the chart container from ariaLabel %p', ( ariaLabel, name ) => {
renderWithTheme( { ariaLabel } );
expect( screen.getByRole( 'application', { name } ) ).toBeInTheDocument();
expect( screen.queryByLabelText( 'XYChart' ) ).not.toBeInTheDocument();
} );

Expand Down
2 changes: 0 additions & 2 deletions projects/js-packages/charts/src/charts/bar-chart/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ export type BandHighlightSelection = {
};

export interface BarChartProps extends BaseChartProps< SeriesData[] >, SeriesVisibilityProps {
/** Accessible name of the chart. Defaults to a localized "Bar chart". */
ariaLabel?: string;
/**
* Legend configuration. Supports `collapseGroups` on top of the shared options.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { formatNumberCompact } from '@automattic/number-formatters';
import { Group } from '@visx/group';
import { createScale, scaleBand } from '@visx/scale';
import { Text, type TextProps } from '@visx/text';
import { __ } from '@wordpress/i18n';
import clsx from 'clsx';
import { useContext, useMemo } from 'react';
import { GlobalChartsContext, GlobalChartsProvider, useGlobalChartsContext } from '../../providers';
Expand Down Expand Up @@ -235,6 +236,7 @@ const BarListChartInternal: FC< BarListChartProps > = ( {
top: 0,
},
className,
ariaLabel,
...rest
} ) => {
const { getElementStyles } = useGlobalChartsContext();
Expand Down Expand Up @@ -333,6 +335,7 @@ const BarListChartInternal: FC< BarListChartProps > = ( {
xScale: chartOptions.xScale,
yScale: chartOptions.yScale,
} }
ariaLabel={ ariaLabel ?? __( 'Bar list chart', 'jetpack-charts' ) }
{ ...rest }
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A horizontal bar chart component optimized for list-style data presentation.
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| `data` | `SeriesData[]` | - | **Required.** Array of series data objects |
| `ariaLabel` | `string` | `'Bar chart'` | Accessible name of the chart. Name it after what it shows; give each chart on a page a different name. |
| `ariaLabel` | `string` | `'Bar list chart'` | Accessible name. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names). |
| `width` | `number` | - | Chart width in pixels |
| `height` | `number` | `400` | Chart height in pixels |
| `aspectRatio` | `number` | - | Height-to-width ratio (e.g. `0.4`) for responsive charts; the chart is contained within its parent on both axes. Used when `width`/`height` are omitted. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ Override automatic positioning when needed:

## Accessibility

BarListChart inherits accessibility features from the underlying BarChart component, including keyboard navigation support when tooltips are enabled and proper ARIA attributes for screen readers.
BarListChart inherits accessibility features from the underlying BarChart component, including keyboard navigation support when tooltips are enabled and proper ARIA attributes for screen readers. See [Bar Chart accessibility](./?path=/docs/js-packages-charts-library-charts-bar-chart--docs#accessibility).

## Migration from Bar Chart

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useTooltip } from '@visx/tooltip';
import { __ } from '@wordpress/i18n';
import { Stack } from '@wordpress/ui';
import clsx from 'clsx';
import { type FC, useRef, useMemo, useEffect, useState, useCallback, useContext } from 'react';
Expand Down Expand Up @@ -30,6 +31,7 @@ import type { FunnelStep, ConversionFunnelChartProps } from './types';
* @param props.loading - Whether the chart is in loading state
* @param props.animation - Whether to show chart animation on initial render or not
* @param props.className - Additional CSS class name
* @param props.ariaLabel - Accessible name for the chart group
* @param props.height - Height of the chart container. Falls back to style.height if set, otherwise defaults to "100%".
* @param props.style - Custom styling
* @param props.renderStepLabel - Custom render function for step labels
Expand All @@ -46,6 +48,7 @@ const ConversionFunnelChartInternal: FC< ConversionFunnelChartProps > = ( {
loading = false,
animation,
className,
ariaLabel,
chartId: providedChartId,
height,
style,
Expand Down Expand Up @@ -311,6 +314,8 @@ const ConversionFunnelChartInternal: FC< ConversionFunnelChartProps > = ( {
direction="column"
gap="xl"
data-testid="conversion-funnel-chart"
role="group"
aria-label={ ariaLabel ?? __( 'Conversion funnel chart', 'jetpack-charts' ) }
ref={ setChartRef }
className={ clsx(
'conversion-funnel-chart',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Main component for displaying conversion funnel visualizations.
| `mainRate` | `number` | - | **Required.** Main conversion rate to highlight (0-100) |
| `steps` | `FunnelStep[]` | - | **Required.** Array of funnel steps |
| `changeIndicator` | `string` | - | Change indicator (e.g., "+2%", "-1.5%") |
| `ariaLabel` | `string` | `'Conversion funnel chart'` | Accessible name. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names). |
| `loading` | `boolean` | `false` | Whether the chart is in loading state |
| `animation` | `boolean` | `false` | Enable entry animation on initial render. Funnel bars grow from bottom to full height. Automatically respects user's `prefers-reduced-motion` system setting |
| `height` | `string \| number` | `"100%"` | Height of the chart container. Accepts a number (pixels) or CSS string (e.g., `"400px"`, `"100%"`). Falls back to `style.height` if set, otherwise defaults to `"100%"` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ Measure content consumption funnel from page views to conversions.

### Screen Reader Support

- Set `ariaLabel` to name the chart. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names).
- **ARIA Roles**: Each funnel step uses `role="button"` for proper semantic meaning
- **ARIA Labels**: Each step has `aria-label` with the step name
- **Alternative Text**: Step labels and rates are accessible to screen readers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export interface TooltipRenderProps {
*/
export interface ConversionFunnelChartProps extends Pick<
BaseChartProps,
'className' | 'chartId' | 'animation'
'className' | 'chartId' | 'animation' | 'ariaLabel'
> {
/** Main conversion rate to highlight */
mainRate: number;
Expand Down
19 changes: 17 additions & 2 deletions projects/js-packages/charts/src/charts/geo-chart/geo-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ function normalizeGeoChartError( eventArgs: unknown ): GeoChartError {
*
* @param props - The props for the GeoChart component
* @param props.data - Data in Google Charts format (array of arrays with headers)
* @param props.ariaLabel - Accessible name of the chart
* @param props.width - Width of the chart in pixels
* @param props.height - Height of the chart in pixels
* @param props.region - Region to display ('world', 'US', or ISO 3166-1 alpha-2 code)
Expand All @@ -140,6 +141,7 @@ function normalizeGeoChartError( eventArgs: unknown ): GeoChartError {
const GeoChartInternal: FC< GeoChartProps > = ( {
className,
data,
ariaLabel,
width,
height,
region = 'world',
Expand Down Expand Up @@ -289,12 +291,23 @@ const GeoChartInternal: FC< GeoChartProps > = ( {
]
);

const chartEvents = useMemo< ReactGoogleChartEvent[] | undefined >( () => {
const chartEvents = useMemo< ReactGoogleChartEvent[] >( () => {
const readyEvent: ReactGoogleChartEvent = {
eventName: 'ready',
// Google hardcodes aria-label="A chart." on its SVG, which repeats the chart's own name.
callback: () => {
containerRef.current
?.querySelectorAll( 'svg' )
.forEach( svg => svg.setAttribute( 'aria-hidden', 'true' ) );
},
};

if ( ! onError ) {
return undefined;
return [ readyEvent ];
}

return [
readyEvent,
{
eventName: 'error',
callback: ( { eventArgs } ) => {
Expand All @@ -307,6 +320,8 @@ const GeoChartInternal: FC< GeoChartProps > = ( {
return (
<Center
ref={ containerRef }
role="group"
aria-label={ ariaLabel ?? __( 'Geo chart', 'jetpack-charts' ) }
className={ clsx( 'geo-chart', styles.container, className ) }
data-testid="geo-chart"
style={ { width, height } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Main component for rendering geographical data on an interactive world map using
| `displayMode` | `GeoDisplayMode` | `'regions'` | `'regions'` shades each area the rows name; `'markers'` draws a circle per row, placed by name or by `[ latitude, longitude ]` in the first two columns |
| `domain` | `string` | - | ISO 3166-1 alpha-2 code of the country whose viewpoint sets the disputed borders (e.g., `'IN'`). Google's default borders apply when omitted |
| `onError` | `(error: GeoChartError) => void` | - | Callback fired when Google Charts emits a chart error, including draw errors Google renders into the chart container (e.g. a missing map file) |
| `ariaLabel` | `string` | `'Geo chart'` | Accessible name. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names). |
| `className` | `string` | - | Additional CSS class name for the chart container |
| `chartId` | `string` | - | Custom chart identifier for accessibility |
| `renderPlaceholder` | `() => React.ReactNode` | - | Optional render function for custom loading placeholder. Called while Google Charts is loading |
Expand All @@ -29,7 +30,7 @@ Main component for rendering geographical data on an interactive world map using

```typescript
interface GeoChartProps
extends Pick<BaseChartProps, 'className' | 'chartId' | 'width' | 'height'> {
extends Pick<BaseChartProps, 'className' | 'chartId' | 'width' | 'height' | 'ariaLabel'> {
data: GeoData;
region?: GeoRegion;
resolution?: GeoResolution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,9 @@ The Geo Chart uses Google Charts' default Mercator projection for world map visu

### Screen Reader Support

Google Charts provides some built-in accessibility features. For better accessibility:

- Set `ariaLabel` to name the chart. See [Accessible names](./?path=/docs/js-packages-charts-library-introduction--docs#accessible-names).
- Provide a data table or list alongside the chart
- Use descriptive headings to introduce the geographical data
- Consider adding `aria-label` or `aria-describedby` to the container element

### Focus Management

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,13 +281,18 @@ describe( 'GeoChart', () => {
} );

describe( 'Chart Events', () => {
test( 'does not pass chart events when onError is omitted', () => {
test( "hides Google's own SVG label from screen readers once the map is ready", () => {
renderWithTheme();

const chartEvents = screen.getByTestId( 'chart-events' );
const events = JSON.parse( chartEvents.textContent || '[]' );
const svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
screen.getByTestId( 'google-chart-mock' ).appendChild( svg );

expect( events ).toEqual( [] );
const chartProps = ChartMock.mock.calls[ ChartMock.mock.calls.length - 1 ]?.[ 0 ];
chartProps.chartEvents
.find( ( event: { eventName: string } ) => event.eventName === 'ready' )
.callback( {} );

expect( svg ).toHaveAttribute( 'aria-hidden', 'true' );
} );

test( 'calls onError when Google Charts emits an error', () => {
Expand Down
Loading
Loading