Skip to content

Commit ad6a29a

Browse files
authored
chore: Alternative column series highlight effect (#43)
* chore: Alternative column series highlight effect * add vr page * include single series chart
1 parent 9ec6219 commit ad6a29a

File tree

4 files changed

+132
-6
lines changed

4 files changed

+132
-6
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import ColumnLayout from "@cloudscape-design/components/column-layout";
5+
6+
import CoreChart from "../../lib/components/internal-do-not-use/core-chart";
7+
import { dateFormatter } from "../common/formatters";
8+
import { useChartSettings } from "../common/page-settings";
9+
import { Page, PageSection } from "../common/templates";
10+
11+
const domain = [
12+
new Date(1601071200000),
13+
new Date(1601078400000),
14+
new Date(1601085600000),
15+
new Date(1601092800000),
16+
new Date(1601100000000),
17+
];
18+
19+
export default function () {
20+
return (
21+
<Page title="Column series hover visual regression page">
22+
<ColumnLayout columns={3}>
23+
<PageSection>
24+
<Chart type="stacked" />
25+
</PageSection>
26+
<PageSection>
27+
<Chart type="grouped" />
28+
</PageSection>
29+
<PageSection>
30+
<Chart type="single" />
31+
</PageSection>
32+
</ColumnLayout>
33+
</Page>
34+
);
35+
}
36+
37+
function Chart({ type }: { type: "single" | "stacked" | "grouped" }) {
38+
const { chartProps } = useChartSettings();
39+
return (
40+
<CoreChart
41+
highcharts={chartProps.cartesian.highcharts}
42+
ariaLabel="Bar chart"
43+
legend={{ enabled: false }}
44+
tooltip={{ placement: "outside" }}
45+
options={{
46+
plotOptions: { series: { stacking: type === "stacked" ? "normal" : undefined } },
47+
series: [
48+
{
49+
name: "Severe",
50+
type: "column" as const,
51+
data: [22, 28, 25, 13, 28],
52+
},
53+
{
54+
name: "Moderate",
55+
type: "column" as const,
56+
data: [18, 21, 22, 0, 1],
57+
},
58+
{
59+
name: "Low",
60+
type: "column" as const,
61+
data: [17, 19, 18, 17, 15],
62+
},
63+
{
64+
name: "Unclassified",
65+
type: "column" as const,
66+
data: [24, 18, 16, 14, 16],
67+
},
68+
].slice(0, type === "single" ? 1 : 4),
69+
xAxis: [
70+
{
71+
type: "category",
72+
title: { text: "Time (UTC)" },
73+
categories: domain.map((date) => dateFormatter(date.getTime())),
74+
},
75+
],
76+
yAxis: [{ title: { text: "Error count" } }],
77+
}}
78+
callback={(api) => {
79+
setTimeout(() => {
80+
if (api.chart.series) {
81+
const seriesIndex = Math.min(api.chart.series.length - 1, 1);
82+
const point = api.chart.series[seriesIndex].data.find((p) => p.x === 2)!;
83+
api.highlightChartPoint(point);
84+
}
85+
}, 0);
86+
}}
87+
/>
88+
);
89+
}

src/core/__tests__/chart-core-highlight.test.tsx

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { act } from "react";
55
import highcharts from "highcharts";
66

77
import "highcharts/highcharts-more";
8-
import { createChartWrapper, renderChart } from "./common";
8+
import { renderChart } from "./common";
99
import { HighchartsTestHelper } from "./highcharts-utils";
1010

1111
const hc = new HighchartsTestHelper(highcharts);
@@ -42,7 +42,6 @@ describe("CoreChart: highlight", () => {
4242
},
4343
});
4444

45-
expect(createChartWrapper().findLegend()).not.toBe(null);
4645
expect(hc.getChartSeries(0).state).toBe("");
4746
expect(hc.getChartSeries(1).state).toBe("");
4847
expect(hc.getChartSeries(2).state).toBe("");
@@ -63,4 +62,42 @@ describe("CoreChart: highlight", () => {
6362
expect(hc.getChartSeries(2).state).toBe("");
6463
expect(hc.getChartSeries(3).state).toBe("");
6564
});
65+
66+
test.each([{ stacked: false }, { stacked: true }])(
67+
"highlights a single group/stack, stacked=$stacked",
68+
async ({ stacked }) => {
69+
renderChart({
70+
highcharts,
71+
options: {
72+
plotOptions: { series: { stacking: stacked ? "normal" : undefined } },
73+
series: [
74+
{ type: "column", name: "C1", data: [1, 2] },
75+
{ type: "column", name: "C2", data: [3, 4] },
76+
],
77+
},
78+
});
79+
80+
expect(hc.getChartSeries(0).state).toBe("");
81+
expect(hc.getChartSeries(1).state).toBe("");
82+
83+
act(() => hc.highlightChartPoint(1, 0));
84+
85+
expect(hc.getChartSeries(0).state).toBe("inactive");
86+
expect(hc.getChartPoint(0, 0).state).toBe("inactive");
87+
expect(hc.getChartPoint(0, 1).state).toBe("inactive");
88+
expect(hc.getChartSeries(1).state).toBe("hover");
89+
expect(hc.getChartPoint(1, 0).state).toBe("hover");
90+
expect(hc.getChartPoint(1, 1).state).toBe("inactive");
91+
92+
act(() => hc.leaveChartPoint(1, 0));
93+
await clearHighlightPause();
94+
95+
expect(hc.getChartSeries(0).state).toBe("");
96+
expect(hc.getChartPoint(0, 0).state).toBe("");
97+
expect(hc.getChartPoint(0, 1).state).toBe("");
98+
expect(hc.getChartSeries(1).state).toBe("");
99+
expect(hc.getChartPoint(1, 0).state).toBe("");
100+
expect(hc.getChartPoint(1, 1).state).toBe("");
101+
},
102+
);
66103
});

src/core/chart-api/chart-extra-highlight.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class ChartExtraHighlight {
6262
});
6363
for (const s of this.context.chart().series) {
6464
this.setSeriesState(s, includedSeries.has(s) ? "" : "inactive");
65-
// We use special handling for column- series to make stacks or groups of columns that have a shared X highlighted.
65+
// For column series we ensure only one group/stack that matches selected X is highlighted.
6666
// See: https://github.com/highcharts/highcharts/issues/23076.
6767
if (s.type === "column") {
6868
for (const d of s.data) {
@@ -86,10 +86,10 @@ export class ChartExtraHighlight {
8686
}
8787
this.setPointState(point, "hover");
8888
}
89-
// We override point state that could have been set for columns using this.highlightChartGroup().
89+
// For column series we ensure only one group/stack that matches selected X is highlighted.
9090
else if (s.type === "column") {
9191
for (const d of s.data) {
92-
this.setPointState(d, "");
92+
this.setPointState(d, d === point ? "hover" : "inactive");
9393
}
9494
}
9595
}

src/internal/chart-styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export const seriesDataLabelsCss: Highcharts.CSSObject = {
133133
textOutline: "",
134134
};
135135

136-
export const seriesOpacityInactive = 0.2;
136+
export const seriesOpacityInactive = 0.3;
137137

138138
export const verticalAxisTitleBlockSize = 24;
139139
export const verticalAxisTitleMargin = 4;

0 commit comments

Comments
 (0)