diff --git a/CLAUDE.md b/CLAUDE.md
index 69844598916..20e3779f679 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -127,6 +127,10 @@ const style = {
Components must work in both SPA and SSR environments. Wrappers use `suppressHydrationWarning` because web component internal state doesn't serialize consistently.
+### CSS Modules
+
+Component styles use CSS Modules (`.module.css` files). The corresponding `.css.ts` files are **auto-generated** by the build system and **gitignored** (`src/**/*.css.ts` in each package's `.gitignore`). Never create or edit `.css.ts` files manually — only create the `.module.css` source file.
+
## Core Architecture
### Base Package Imports
diff --git a/packages/charts/src/components/ScatterChart/ScatterChart.cy.tsx b/packages/charts/src/components/ScatterChart/ScatterChart.cy.tsx
index e2793419442..b243c6d184f 100644
--- a/packages/charts/src/components/ScatterChart/ScatterChart.cy.tsx
+++ b/packages/charts/src/components/ScatterChart/ScatterChart.cy.tsx
@@ -19,6 +19,17 @@ const measures = [
},
];
+function activePointLabelShould(containerSelector: string, ...matchers: string[]) {
+ cy.get(containerSelector)
+ .should('have.attr', 'aria-activedescendant')
+ .then((activeId) => {
+ let chain = cy.get(`#${CSS.escape(activeId as string)}`).should('have.attr', 'aria-label');
+ for (const m of matchers) {
+ chain = chain.and('contain', m);
+ }
+ });
+}
+
describe('ScatterChart', () => {
it('Basic', () => {
cy.mount();
@@ -66,7 +77,204 @@ describe('ScatterChart', () => {
it('Loading Placeholder', () => {
cy.mount();
cy.get('.recharts-scatter').should('not.exist');
- cy.contains('Loading...').should('exist');
+ cy.findByText('Loading...').should('exist');
+ });
+
+ it('accessibilityLayer: keyboard navigation, Enter, blur/re-focus, consumer handlers', () => {
+ const chartConfig = { accessibilityLayer: true };
+ const containerSelector = '[aria-roledescription="chart"]';
+ const singleDataset = [
+ {
+ label: 'Series A',
+ data: [
+ { users: 100, sessions: 200, volume: 300 },
+ { users: 50, sessions: 150, volume: 250 },
+ { users: 200, sessions: 400, volume: 500 },
+ ],
+ },
+ ];
+
+ const onDataPointClick = cy.spy().as('onDataPointClick');
+ const onBlur = cy.spy().as('onBlur');
+ const onFocus = cy.spy().as('onFocus');
+ const onKeyDownCapture = cy.spy().as('onKeyDownCapture');
+
+ cy.mount(
+ <>
+
+
+
+ >,
+ );
+ cy.get('[role="img"][aria-label]').should('have.length', 3);
+
+ cy.findByText('before').focus();
+
+ // container focused, first scatter "active"
+ cy.realPress('Tab');
+ cy.focused()
+ .should('have.attr', 'tabindex', '0')
+ .should('have.attr', 'role', 'application')
+ .should('have.attr', 'aria-roledescription', 'chart');
+ cy.get('@onFocus').should('have.been.calledOnce');
+ activePointLabelShould(containerSelector, 'Number: 50');
+ cy.get('[data-point-focused]').should('have.length', 1);
+
+ // 2nd scatter "active" - forward by X
+ cy.realPress('ArrowRight');
+ activePointLabelShould(containerSelector, 'Number: 100');
+ cy.get('@onKeyDownCapture').should('have.been.called');
+
+ // 3rd scatter "active"
+ cy.realPress('ArrowRight');
+ activePointLabelShould(containerSelector, 'Number: 200');
+
+ // 3rd scatter "active" -> last one
+ cy.realPress('ArrowRight');
+ activePointLabelShould(containerSelector, 'Number: 200');
+
+ // 2nd scatter "active"
+ cy.realPress('ArrowLeft');
+ activePointLabelShould(containerSelector, 'Number: 100');
+
+ cy.realPress('Enter');
+ cy.get('@onDataPointClick').should(
+ 'have.been.calledWith',
+ Cypress.sinon.match({
+ detail: Cypress.sinon.match({ payload: singleDataset[0].data[0] }),
+ }),
+ );
+
+ cy.get('[role="img"][aria-label]').eq(2).click();
+ cy.get('@onDataPointClick').should('have.been.calledTwice');
+ activePointLabelShould(containerSelector, 'Number: 200');
+
+ // Leave chart
+ cy.realPress('Tab');
+ cy.focused().should('contain.text', 'after');
+ cy.get(containerSelector).should('not.have.attr', 'aria-activedescendant');
+ cy.get('[data-point-focused]').should('not.exist');
+ cy.get('@onBlur').should('have.been.called');
+
+ // Reenter chart
+ cy.realPress(['Shift', 'Tab']);
+ cy.focused().should('have.attr', 'aria-roledescription', 'chart');
+ activePointLabelShould(containerSelector, 'Number: 200');
+
+ cy.realPress('ArrowLeft');
+ activePointLabelShould(containerSelector, 'Number: 100');
+ cy.realPress('ArrowLeft');
+ activePointLabelShould(containerSelector, 'Number: 50');
+ cy.realPress('ArrowLeft');
+ activePointLabelShould(containerSelector, 'Number: 50');
+ });
+
+ it('accessibilityLayer: multi-dataset points sorted by X then datasetIndex', () => {
+ const chartConfig = { accessibilityLayer: true };
+ const containerSelector = '[aria-roledescription="chart"]';
+ const multiDataset = [
+ {
+ label: 'Alpha',
+ data: [{ users: 30, sessions: 100, volume: 200 }],
+ },
+ {
+ label: 'Beta',
+ data: [
+ { users: 30, sessions: 150, volume: 250 },
+ { users: 60, sessions: 300, volume: 400 },
+ ],
+ },
+ ];
+
+ cy.mount(
+ <>
+
+
+ >,
+ );
+
+ cy.get('[role="img"][aria-label]').should('have.length', 3);
+ cy.findByText('before').focus();
+ cy.realPress('Tab');
+
+ // Same X value (30): sorted by dataset index, Alpha (0) before Beta (1)
+ activePointLabelShould(containerSelector, 'Alpha');
+ cy.realPress('ArrowRight');
+ activePointLabelShould(containerSelector, 'Beta', 'Number: 30');
+ cy.realPress('ArrowRight');
+ activePointLabelShould(containerSelector, 'Beta', 'Number: 60');
+ });
+
+ it('accessibilityLayer: multiple charts', () => {
+ const chartConfig = { accessibilityLayer: true };
+ const singleDataset = [
+ {
+ label: 'Series A',
+ data: [
+ { users: 100, sessions: 200, volume: 300 },
+ { users: 50, sessions: 150, volume: 250 },
+ ],
+ },
+ ];
+
+ cy.mount(
+ <>
+
+
+
+
+ >,
+ );
+
+ cy.get('[role="img"][id]').then(($els) => {
+ const ids = [...$els].map((el) => el.id);
+ expect(new Set(ids).size).to.equal(ids.length);
+ });
+
+ cy.findByText('before').focus();
+ cy.realPress('Tab');
+ cy.focused().should('have.attr', 'aria-roledescription', 'chart1');
+ cy.realPress('ArrowRight');
+ activePointLabelShould('[aria-roledescription="chart1"]:first', 'Number: 100');
+
+ cy.realPress('Tab');
+ cy.focused().should('have.attr', 'aria-roledescription', 'chart2');
+ cy.realPress('ArrowRight');
+ activePointLabelShould('[aria-roledescription="chart2"]:first', 'Number: 100');
+
+ cy.realPress('Tab');
+ cy.focused().should('contain.text', 'after');
+ });
+
+ [false, true].forEach((accessibilityLayer) => {
+ it(`empty dataset (accessibilityLayer: ${accessibilityLayer})`, () => {
+ cy.mount();
+ cy.get('.recharts-scatter').should('not.exist');
+ cy.findByText('Loading...').should('exist');
+ if (accessibilityLayer) {
+ cy.get('[aria-roledescription="chart"]')
+ .should('have.attr', 'tabindex', '0')
+ .should('not.have.attr', 'role', 'application');
+ }
+ });
});
testChartLegendConfig(ScatterChart, { dataset: complexDataSet, measures });
diff --git a/packages/charts/src/components/ScatterChart/ScatterChart.mdx b/packages/charts/src/components/ScatterChart/ScatterChart.mdx
index 626c9ca463c..70cbeffe4a0 100644
--- a/packages/charts/src/components/ScatterChart/ScatterChart.mdx
+++ b/packages/charts/src/components/ScatterChart/ScatterChart.mdx
@@ -25,6 +25,10 @@ import LegendStory from '../../resources/LegendConfig.mdx';
+### With Accessibility Layer
+
+
+
### Loading Placeholder
diff --git a/packages/charts/src/components/ScatterChart/ScatterChart.module.css b/packages/charts/src/components/ScatterChart/ScatterChart.module.css
new file mode 100644
index 00000000000..6de41a56bcb
--- /dev/null
+++ b/packages/charts/src/components/ScatterChart/ScatterChart.module.css
@@ -0,0 +1,13 @@
+.scatterchart {
+ g:focus,
+ path:focus {
+ outline: none;
+ }
+
+ :global(.recharts-scatter-symbol):focus path,
+ :global(.recharts-scatter-symbol)[data-point-focused] path {
+ stroke: var(--sapContent_FocusColor);
+ stroke-width: calc(var(--sapContent_FocusWidth) * 2);
+ paint-order: stroke;
+ }
+}
diff --git a/packages/charts/src/components/ScatterChart/ScatterChart.stories.tsx b/packages/charts/src/components/ScatterChart/ScatterChart.stories.tsx
index b15b5ca6378..5377032fedd 100644
--- a/packages/charts/src/components/ScatterChart/ScatterChart.stories.tsx
+++ b/packages/charts/src/components/ScatterChart/ScatterChart.stories.tsx
@@ -60,6 +60,12 @@ export const WithCustomColor: Story = {
},
};
+export const WithAccessibilityLayer: Story = {
+ args: {
+ chartConfig: { accessibilityLayer: true },
+ },
+};
+
export const LoadingPlaceholder: Story = {
args: {
dataset: [],
diff --git a/packages/charts/src/components/ScatterChart/index.tsx b/packages/charts/src/components/ScatterChart/index.tsx
index d3d018e974d..68c9a1c6239 100644
--- a/packages/charts/src/components/ScatterChart/index.tsx
+++ b/packages/charts/src/components/ScatterChart/index.tsx
@@ -1,8 +1,9 @@
'use client';
-import { useIsRTL, useSyncRef } from '@ui5/webcomponents-react-base/internal/hooks';
+import { useIsRTL, useStylesheet, useSyncRef } from '@ui5/webcomponents-react-base/internal/hooks';
import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/internal/utils';
import { ThemingParameters } from '@ui5/webcomponents-react-base/ThemingParameters';
+import { clsx } from 'clsx';
import type { CSSProperties } from 'react';
import { forwardRef, useCallback, useRef } from 'react';
import type { ReferenceLineProps } from 'recharts';
@@ -32,6 +33,8 @@ import { tickLineConfig, tooltipContentStyle, tooltipFillOpacity, xAxisPadding }
import { XAxisTicks } from '../../internal/XAxisTicks.js';
import { YAxisTicks } from '../../internal/YAxisTicks.js';
import { ScatterChartPlaceholder } from './Placeholder.js';
+import { classNames, styleData } from './ScatterChart.module.css.js';
+import { useScatterPointFocus } from './useScatterPointFocus.js';
interface MeasureConfig extends Omit {
/**
@@ -215,9 +218,43 @@ const ScatterChart = forwardRef((props, ref)
const [yAxisWidth, legendPosition] = useLongestYAxisLabel(dataset?.[0]?.data, [yMeasure], chartConfig.legendPosition);
const xAxisHeights = useObserveXAxisHeights(chartRef, 1);
const marginChart = useChartMargin(chartConfig.margin, chartConfig.zoomingTool);
- const { chartConfig: _0, measures: _1, ...propsWithoutOmitted } = rest;
+ const {
+ chartConfig: _0,
+ measures: _1,
+ onBlur: consumerOnBlur,
+ onFocus: consumerOnFocus,
+ onKeyDownCapture: consumerOnKeyDownCapture,
+ ...propsWithoutOmitted
+ } = rest;
const isRTL = useIsRTL(chartRef);
+ useStylesheet(styleData, ScatterChart.displayName);
+
+ const { containerProps: pointFocusProps, handlePointClick } = useScatterPointFocus({
+ chartRef,
+ enabled: !!chartConfig.accessibilityLayer,
+ dataset: dataset ?? [],
+ measures,
+ consumerOnBlur,
+ consumerOnFocus,
+ consumerOnKeyDownCapture,
+ onSelect: useCallback(
+ (point, e) => {
+ if (typeof onDataPointClick !== 'function') {
+ return;
+ }
+ onDataPointClick(
+ enrichEventWithDetails(e as unknown as CustomEvent, {
+ value: point.raw,
+ dataIndex: point.pointIndex,
+ payload: point.raw,
+ }),
+ );
+ },
+ [onDataPointClick],
+ ),
+ });
+
return (
((props, ref)
className={className}
slot={slot}
resizeDebounce={chartConfig.resizeDebounce}
+ {...pointFocusProps}
{...propsWithoutOmitted}
>
((props, ref)
return (
{
+ onDataPointClickInternal(payload, pointIndex, event);
+ handlePointClick?.(index, pointIndex);
+ }}
opacity={dataSet.opacity}
data={dataSet?.data}
name={dataSet?.label}
key={dataSet?.label}
fill={dataSet?.color ?? `var(--sapChart_OrderedColor_${(index % 12) + 1})`}
- isAnimationActive={!noAnimation}
+ // Animation recreates DOM elements, wiping a11y attributes.
+ isAnimationActive={!noAnimation && !chartConfig.accessibilityLayer}
/>
);
})}
diff --git a/packages/charts/src/components/ScatterChart/useScatterPointFocus.ts b/packages/charts/src/components/ScatterChart/useScatterPointFocus.ts
new file mode 100644
index 00000000000..c827b3c3d59
--- /dev/null
+++ b/packages/charts/src/components/ScatterChart/useScatterPointFocus.ts
@@ -0,0 +1,325 @@
+import type { FocusEvent, FocusEventHandler, KeyboardEvent, KeyboardEventHandler, RefObject } from 'react';
+import { useCallback, useEffect, useId, useMemo, useRef } from 'react';
+
+interface MeasureInfo {
+ accessor: string | ((entry: Record) => unknown);
+ label?: string;
+ formatter?: (value: unknown) => string;
+ axis: 'x' | 'y' | 'z';
+}
+
+interface ScatterDataset {
+ label?: string;
+ data?: Record[];
+ color?: string;
+ opacity?: number;
+}
+
+interface FlatPoint {
+ datasetIndex: number;
+ pointIndex: number;
+ datasetLabel: string;
+ raw: Record;
+}
+
+interface UseScatterPointFocusOptions {
+ chartRef: RefObject;
+ enabled: boolean;
+ dataset: ScatterDataset[];
+ measures: MeasureInfo[];
+ onSelect?: (point: FlatPoint, event: KeyboardEvent) => void;
+ consumerOnBlur?: FocusEventHandler;
+ consumerOnFocus?: FocusEventHandler;
+ consumerOnKeyDownCapture?: KeyboardEventHandler;
+}
+
+// Resolves an accessor (string key or getter function) to the value from a data entry.
+function getAccessorValue(
+ entry: Record,
+ accessor: string | ((e: Record) => unknown),
+) {
+ if (typeof accessor === 'function') {
+ return accessor(entry);
+ }
+ return entry[accessor];
+}
+
+// Builds the aria-label string for a point: "DatasetLabel, MeasureLabel: value, ..."
+function getPointLabel(point: FlatPoint, measures: MeasureInfo[]) {
+ const parts: string[] = [];
+ if (point.datasetLabel) {
+ parts.push(point.datasetLabel);
+ }
+ for (const m of measures) {
+ const value = getAccessorValue(point.raw, m.accessor);
+ const formatted = m.formatter ? m.formatter(value) : String((value as string) ?? '');
+ const label = m.label || (typeof m.accessor === 'string' ? m.accessor : m.axis);
+ parts.push(`${label}: ${formatted}`);
+ }
+ return parts.join(', ');
+}
+
+/**
+ * Manages keyboard navigation through scatter chart data points using aria-activedescendant.
+ *
+ * Single tab stop: focusing the chart immediately activates the first (or last-visited) point.
+ * Arrow keys navigate between points sorted by X value. Tab/Shift+Tab leave the chart naturally.
+ *
+ * Static attributes (id, role, aria-label) are applied to all symbols via effect.
+ * Only `data-point-focused` and `aria-activedescendant` change during navigation.
+ *
+ * Active when `chartConfig.accessibilityLayer` is enabled.
+ */
+export function useScatterPointFocus({
+ chartRef,
+ enabled,
+ dataset,
+ measures,
+ onSelect,
+ consumerOnBlur,
+ consumerOnFocus,
+ consumerOnKeyDownCapture,
+}: UseScatterPointFocusOptions) {
+ const pointFocusRef = useRef(-1);
+ const spaceHeldRef = useRef(false);
+ const baseId = useId();
+
+ const xMeasure = measures.find((m) => m.axis === 'x');
+
+ // flatten dataset and sort by x-axis value for arrow key nav
+ const flatPoints: FlatPoint[] = useMemo(() => {
+ if (!dataset?.length || !xMeasure) {
+ return [];
+ }
+ const points: FlatPoint[] = [];
+ dataset.forEach((ds, dsIndex) => {
+ ds.data?.forEach((entry, ptIndex) => {
+ points.push({
+ datasetIndex: dsIndex,
+ pointIndex: ptIndex,
+ datasetLabel: ds.label ?? '',
+ raw: entry,
+ });
+ });
+ });
+ points.sort((a, b) => {
+ const ax = Number(getAccessorValue(a.raw, xMeasure.accessor)) || 0;
+ const bx = Number(getAccessorValue(b.raw, xMeasure.accessor)) || 0;
+ if (ax !== bx) {
+ return ax - bx;
+ }
+ return a.datasetIndex - b.datasetIndex;
+ });
+ return points;
+ }, [dataset, xMeasure]);
+
+ // mutable ref for event handler data (reset when data changes)
+ const flatPointsRef = useRef(flatPoints);
+ useEffect(() => {
+ flatPointsRef.current = flatPoints;
+ pointFocusRef.current = -1;
+ }, [flatPoints]);
+
+ // Recharts recreates DOM elements on rerender -> must set attributes again after each update
+ useEffect(() => {
+ if (!enabled) {
+ return;
+ }
+ const container = chartRef.current;
+ if (!container) {
+ return;
+ }
+
+ const allSymbols: SVGGElement[][] = [];
+ container.querySelectorAll('.recharts-scatter').forEach((group) => {
+ allSymbols.push(Array.from(group.querySelectorAll(':scope .recharts-scatter-symbol')));
+ });
+ if (allSymbols.length === 0) {
+ return;
+ }
+
+ // Set a11y attributes on each scatter symbol.
+ for (let idx = 0; idx < flatPoints.length; idx++) {
+ const point = flatPoints[idx];
+ const el = allSymbols[point.datasetIndex]?.[point.pointIndex];
+ if (!el) {
+ continue;
+ }
+ el.setAttribute('id', `${baseId}-point-${idx}`);
+ el.setAttribute('role', 'img');
+ el.setAttribute('aria-label', getPointLabel(point, measures));
+ }
+
+ // Reapply attributes when chart is updated if it still has focus.
+ const activeIdx = pointFocusRef.current;
+ if (activeIdx >= 0 && container.contains(document.activeElement)) {
+ const el = container.querySelector(`#${CSS.escape(baseId)}-point-${activeIdx}`);
+ if (el) {
+ el.setAttribute('data-point-focused', '');
+ container.setAttribute('aria-activedescendant', `${baseId}-point-${activeIdx}`);
+ }
+ }
+ });
+
+ const activatePoint = useCallback(
+ (index: number) => {
+ const container = chartRef.current;
+ if (!container) {
+ return;
+ }
+
+ container
+ .querySelector('.recharts-scatter-symbol[data-point-focused]')
+ ?.removeAttribute('data-point-focused');
+
+ pointFocusRef.current = index;
+
+ const el = container.querySelector(`#${CSS.escape(baseId)}-point-${index}`);
+ if (!el) {
+ return;
+ }
+
+ el.setAttribute('data-point-focused', '');
+ container.setAttribute('aria-activedescendant', `${baseId}-point-${index}`);
+ },
+ [baseId, chartRef],
+ );
+
+ const clearActivePoint = useCallback(() => {
+ const container = chartRef.current;
+ if (!container) {
+ return;
+ }
+ container
+ .querySelector('.recharts-scatter-symbol[data-point-focused]')
+ ?.removeAttribute('data-point-focused');
+ container.removeAttribute('aria-activedescendant');
+ }, [chartRef]);
+
+ const handleKeyDown = useCallback(
+ (e: KeyboardEvent) => {
+ const points = flatPointsRef.current;
+ if (!points.length) {
+ return;
+ }
+
+ switch (e.key) {
+ case 'ArrowRight':
+ case 'ArrowDown': {
+ e.preventDefault();
+ const next = Math.min(pointFocusRef.current + 1, points.length - 1);
+ activatePoint(next);
+ break;
+ }
+ case 'ArrowLeft':
+ case 'ArrowUp': {
+ e.preventDefault();
+ const prev = Math.max(pointFocusRef.current - 1, 0);
+ activatePoint(prev);
+ break;
+ }
+ case 'Enter': {
+ e.preventDefault();
+ if (pointFocusRef.current >= 0 && typeof onSelect === 'function') {
+ onSelect(points[pointFocusRef.current], e);
+ }
+ break;
+ }
+ case ' ': {
+ // Space fires selection on keyup.
+ e.preventDefault();
+ spaceHeldRef.current = true;
+ break;
+ }
+ }
+ },
+ [activatePoint, onSelect],
+ );
+
+ const handleKeyUp = useCallback(
+ (e: KeyboardEvent) => {
+ if (e.key === ' ' && spaceHeldRef.current) {
+ spaceHeldRef.current = false;
+ const points = flatPointsRef.current;
+ if (pointFocusRef.current >= 0 && typeof onSelect === 'function') {
+ onSelect(points[pointFocusRef.current], e);
+ }
+ }
+ },
+ [onSelect],
+ );
+
+ const handleFocus = useCallback(
+ (e: FocusEvent) => {
+ if (e.target === e.currentTarget) {
+ const index = pointFocusRef.current >= 0 ? pointFocusRef.current : 0;
+ activatePoint(index);
+ }
+ if (typeof consumerOnFocus === 'function') {
+ consumerOnFocus(e);
+ }
+ },
+ [activatePoint, consumerOnFocus],
+ );
+
+ const handleBlur = useCallback(
+ (e: FocusEvent) => {
+ if (!e.currentTarget.contains(e.relatedTarget)) {
+ clearActivePoint();
+ spaceHeldRef.current = false;
+ }
+ if (typeof consumerOnBlur === 'function') {
+ consumerOnBlur(e);
+ }
+ },
+ [clearActivePoint, consumerOnBlur],
+ );
+
+ const handleKeyDownCapture = useCallback(
+ (e: KeyboardEvent) => {
+ handleKeyDown(e);
+ if (typeof consumerOnKeyDownCapture === 'function') {
+ consumerOnKeyDownCapture(e);
+ }
+ },
+ [handleKeyDown, consumerOnKeyDownCapture],
+ );
+
+ const handlePointClick = useCallback(
+ (datasetIndex: number, pointIndex: number) => {
+ const points = flatPointsRef.current;
+ const idx = points.findIndex((p) => p.datasetIndex === datasetIndex && p.pointIndex === pointIndex);
+ if (idx >= 0) {
+ activatePoint(idx);
+ }
+ },
+ [activatePoint],
+ );
+
+ if (!enabled) {
+ return { containerProps: {} as const, handlePointClick: undefined };
+ }
+
+ if (flatPoints.length === 0) {
+ return {
+ containerProps: {
+ tabIndex: 0,
+ 'aria-roledescription': 'chart',
+ } as const,
+ handlePointClick: undefined,
+ };
+ }
+
+ return {
+ containerProps: {
+ tabIndex: 0,
+ role: 'application' as const,
+ 'aria-roledescription': 'chart',
+ onKeyDownCapture: handleKeyDownCapture,
+ onKeyUp: handleKeyUp,
+ onBlur: handleBlur,
+ onFocus: handleFocus,
+ },
+ handlePointClick,
+ };
+}
diff --git a/packages/charts/src/interfaces/IChartBaseProps.ts b/packages/charts/src/interfaces/IChartBaseProps.ts
index 9106546a421..d217053bb0f 100644
--- a/packages/charts/src/interfaces/IChartBaseProps.ts
+++ b/packages/charts/src/interfaces/IChartBaseProps.ts
@@ -109,8 +109,9 @@ export interface IChartBaseProps extends Omit