Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 39 additions & 24 deletions packages/ag-charts-community/src/chart/legend/legendDOMProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,35 +160,14 @@ export class LegendDOMProxy {
this.paginationGroup.setHidden(!pagination.visible);

if (init && 'ctx' in params) {
const { ctx, oldPages, newPages } = params;
const { oldPages, newPages } = params;
const oldNeedsButtons = (oldPages?.length ?? newPages.length) > 1;
const newNeedsButtons = newPages.length > 1;
if (oldNeedsButtons !== newNeedsButtons) {
if (newNeedsButtons) {
this.prevButton = ctx.proxyInteractionService.createProxyElement({
type: 'button',
textContent: { id: 'ariaLabelLegendPagePrevious' },
tabIndex: 0,
parent: this.paginationGroup,
});
this.prevButton.addListener('click', (ev) => this.onPageButton(params, ev, 'previous'));
this.prevButton.addListener('mouseenter', () => pagination.onMouseHover('previous'));
this.prevButton.addListener('mouseleave', () => pagination.onMouseHover(undefined));

this.nextButton ??= ctx.proxyInteractionService.createProxyElement({
type: 'button',
textContent: { id: 'ariaLabelLegendPageNext' },
tabIndex: 0,
parent: this.paginationGroup,
});
this.nextButton.addListener('click', (ev) => this.onPageButton(params, ev, 'next'));
this.nextButton.addListener('mouseenter', () => pagination.onMouseHover('next'));
this.nextButton.addListener('mouseleave', () => pagination.onMouseHover(undefined));
this.createPaginationButtons(params);
} else {
this.nextButton?.destroy();
this.prevButton?.destroy();
this.nextButton = undefined;
this.prevButton = undefined;
this.destroyPaginationButtons();
}
}
this.paginationGroup.setAriaHidden(newNeedsButtons ? undefined : true);
Expand All @@ -211,6 +190,42 @@ export class LegendDOMProxy {
}
}

private createPaginationButtons(params: LegendDOMProxyUpdateParams) {
const { ctx, pagination } = params;

// Only create buttons if they don't exist to prevent duplicate event listeners
if (!this.prevButton) {
this.prevButton = ctx.proxyInteractionService.createProxyElement({
type: 'button',
textContent: { id: 'ariaLabelLegendPagePrevious' },
tabIndex: 0,
parent: this.paginationGroup,
});
this.prevButton.addListener('click', (ev) => this.onPageButton(params, ev, 'previous'));
this.prevButton.addListener('mouseenter', () => pagination.onMouseHover('previous'));
this.prevButton.addListener('mouseleave', () => pagination.onMouseHover(undefined));
}

if (!this.nextButton) {
this.nextButton = ctx.proxyInteractionService.createProxyElement({
type: 'button',
textContent: { id: 'ariaLabelLegendPageNext' },
tabIndex: 0,
parent: this.paginationGroup,
});
this.nextButton.addListener('click', (ev) => this.onPageButton(params, ev, 'next'));
this.nextButton.addListener('mouseenter', () => pagination.onMouseHover('next'));
this.nextButton.addListener('mouseleave', () => pagination.onMouseHover(undefined));
}
}

private destroyPaginationButtons() {
this.nextButton?.destroy();
this.prevButton?.destroy();
this.nextButton = undefined;
this.prevButton = undefined;
}

private onPageButton(params: LegendDOMProxyUpdateParams, ev: MouseWidgetEvent<'click'>, node: 'previous' | 'next') {
params.pagination.onClick(ev.sourceEvent, node);
this.updatePaginationProxyButtons(params, false);
Expand Down
60 changes: 59 additions & 1 deletion packages/ag-charts-website/e2e/legend.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { Locator } from '@playwright/test';

import { expect, test } from './fixture';
import { SELECTORS, gotoExample, setupIntrinsicAssertions, toExamplePageUrls, waitForAllChartUpdates } from './util';
import {
SELECTORS,
gotoExample,
setupIntrinsicAssertions,
toExamplePageUrls,
waitForAllChartUpdates,
waitForChartUpdate,
} from './util';

type RenewablesScreenshotsFilename =
| 'renewables-nothing-highlighted.png'
Expand Down Expand Up @@ -157,4 +164,55 @@ test.describe('legend', () => {
});
});
}

for (const { framework, url } of toExamplePageUrls('legend-test', 'legend-pagination-resize')) {
test.describe(`for ${framework}`, () => {
test('AG-16038 Legend Pagination goes to wrong page after resize hides and shows legend', async ({
page,
}) => {
await gotoExample(page, url);
const chartWrapper = page.locator('.ag-charts-wrapper');
const canvasCenter = page.locator(SELECTORS.canvasCenter);

// Set initial size that should show legend with pagination
await page.setViewportSize({ width: 400, height: 250 });
await waitForChartUpdate(chartWrapper);

// Initial state with legend showing page 1
await expect(canvasCenter).toHaveScreenshot('ag-16038-initial-page-1.png');

// Locate the pagination buttons
const previousButton = page.locator('.ag-charts-proxy-legend-pagination button').first();
const nextButton = page.locator('.ag-charts-proxy-legend-pagination button').last();

// Verify pagination is working - advance to page 2
await nextButton.click();
await waitForChartUpdate(chartWrapper);
await expect(canvasCenter).toHaveScreenshot('ag-16038-legend-page-2-after-click.png');

// Verify pagination is working - go back to page 1
await previousButton.click();
await waitForChartUpdate(chartWrapper);
await expect(canvasCenter).toHaveScreenshot('ag-16038-legend-back-to-page-1-after-click.png');

// Resize to very small width to hide legend
await page.setViewportSize({ width: 230, height: 250 });
await waitForChartUpdate(chartWrapper);
await expect(canvasCenter).toHaveScreenshot('ag-16038-small-size-hidden-legend.png');

// Resize back to normal width - legend should reappear
await page.setViewportSize({ width: 400, height: 250 });
await waitForChartUpdate(chartWrapper);
await expect(canvasCenter).toHaveScreenshot('ag-16038-legend-should-reset-to-page-1.png');

// Verify pagination is working - advance to page 2
const next = page.locator('.ag-charts-proxy-legend-pagination button').last();
await next.click();
await waitForChartUpdate(chartWrapper);
await expect(canvasCenter).toHaveScreenshot(
'ag-16038-legend-page-2-after-resize-hide-unhide-click.png'
);
});
});
}
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function getData() {
return [
{ month: 'Jan', subscriptions: 222, services: 250, products: 200 },
{ month: 'Feb', subscriptions: 240, services: 255, products: 210 },
{ month: 'Mar', subscriptions: 280, services: 245, products: 195 },
{ month: 'Apr', subscriptions: 300, services: 260, products: 205 },
{ month: 'May', subscriptions: 350, services: 235, products: 215 },
{ month: 'Jun', subscriptions: 420, services: 270, products: 200 },
{ month: 'Jul', subscriptions: 300, services: 255, products: 225 },
{ month: 'Aug', subscriptions: 270, services: 305, products: 210 },
{ month: 'Sep', subscriptions: 260, services: 280, products: 250 },
{ month: 'Oct', subscriptions: 385, services: 250, products: 205 },
{ month: 'Nov', subscriptions: 320, services: 265, products: 215 },
{ month: 'Dec', subscriptions: 330, services: 255, products: 220 },
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="resizable-container">
<div id="myChart" class="resizable"></div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { AgCartesianChartOptions, AgChartLegendPosition, AgCharts } from 'ag-charts-community';

import { getData } from './data';

const options: AgCartesianChartOptions = {
container: document.getElementById('myChart'),
data: getData(),
series: [
{
type: 'area',
xKey: 'month',
yKey: 'subscriptions',
yName: 'Subscriptions',
},
{
type: 'area',
xKey: 'month',
yKey: 'services',
yName: 'Services',
},
{
type: 'area',
xKey: 'month',
yKey: 'products',
yName: 'Products',
},
{
type: 'area',
xKey: 'month',
yKey: 'services',
yName: 'Services2',
},
{
type: 'area',
xKey: 'month',
yKey: 'products',
yName: 'Products3',
},
],
};

AgCharts.create(options);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.resizable-container {
height: 100%;
padding: 4px;
height: 100%;
border-radius: 8px;
background-color: color-mix(in srgb, var(--chart-bg), var(--chart-border) 10%);
border: 1px solid var(--chart-border);
overflow: hidden;
}

.resizable {
width: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
resize: both;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,47 @@ Pagination customisation

{% chartExampleRunner title="Legend Pagination" name="legend-pagination" type="generated" /%}

## Legend Interactivity with Pagination

Steps to test:

1. Hover a legend item.
Expected: Pointer cursor is shown.

2. Click on a legend item.
Expected: An alert should appear. No series are toggled.

3. Dismiss alert.

4. Go to page 2/2 on the legend paginator.

5. Hover a legend item.
Expected: Pointer cursor is shown.

6. Click on a legend item.
Expected: An alert appears.

7. Go back to page 1/2 on the legend paginator.

8. Hover a legend item.
Expected: Pointer cursor is shown.

9. Click on a legend item.
Expected: An alert appears.

{% chartExampleRunner title="Legend Interactivity" name="legend-interactivity" type="generated" /%}

## Legend Interactivity Pagination & Page Resize to Hide/Show Legend

Steps to test:

1. Shrink the window width until only one legend item is visible.

2. Shrink the window width until no legend items are visible.

3. Increase the window width until one legend item is visible.

4. Click the pagination 'next' button.
Expected: Legend goes to page 2.

{% chartExampleRunner title="Legend Interactivity" name="legend-pagination-resize" type="generated" /%}
Loading