Skip to content

Commit 0b8e2aa

Browse files
jsilllpan-kot
andauthored
fix: dont render legend container on empty items (#75)
* fix: dont render legend container on empty items * fix empty legend items check * fix no-data placement when legend is on the side * update api snapshot --------- Co-authored-by: Andrei Zhaleznichenka <[email protected]>
1 parent 794af2d commit 0b8e2aa

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import Highcharts from "highcharts";
5+
import { omit } from "lodash";
6+
7+
import Checkbox from "@cloudscape-design/components/checkbox";
8+
9+
import CoreChart from "../../lib/components/internal-do-not-use/core-chart";
10+
import { PageSettings, PageSettingsForm, useChartSettings } from "../common/page-settings";
11+
import { Page } from "../common/templates";
12+
13+
interface ThisPageSettings extends PageSettings {
14+
showInLegend?: boolean;
15+
}
16+
17+
export default function () {
18+
const { chartProps, settings, setSettings } = useChartSettings<ThisPageSettings>();
19+
return (
20+
<Page
21+
title="Empty core chart demo"
22+
settings={
23+
<PageSettingsForm
24+
selectedSettings={[
25+
"showLegend",
26+
"legendPosition",
27+
"showLegendTitle",
28+
"showLegendActions",
29+
"useFallback",
30+
{
31+
content: (
32+
<Checkbox
33+
checked={!!settings.showInLegend}
34+
onChange={({ detail }) => setSettings({ showInLegend: detail.checked })}
35+
>
36+
Show in legend
37+
</Checkbox>
38+
),
39+
},
40+
]}
41+
/>
42+
}
43+
>
44+
<CoreChart
45+
{...omit(chartProps.cartesian, "ref")}
46+
highcharts={Highcharts}
47+
options={{
48+
xAxis: { min: 1, max: 50 },
49+
yAxis: { min: 0, max: 1 },
50+
series: [{ type: "line", data: [], showInLegend: settings.showInLegend }],
51+
}}
52+
/>
53+
</Page>
54+
);
55+
}

src/core/chart-container.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface ChartContainerProps {
3232
legendBottomMaxHeight?: number;
3333
legendPosition: "bottom" | "side";
3434
footer?: React.ReactNode;
35+
noData?: React.ReactNode;
3536
fitHeight?: boolean;
3637
chartHeight?: number;
3738
chartMinHeight?: number;
@@ -49,6 +50,7 @@ export function ChartContainer({
4950
legendPosition,
5051
legendBottomMaxHeight,
5152
navigator,
53+
noData,
5254
fitHeight,
5355
chartHeight,
5456
chartMinHeight,
@@ -85,6 +87,7 @@ export function ChartContainer({
8587
>
8688
{verticalAxisTitle}
8789
{chart(effectiveChartHeight)}
90+
{noData}
8891
</div>
8992
<div className={styles["side-legend-container"]} style={{ maxBlockSize: effectiveChartHeight }}>
9093
{legend}
@@ -107,6 +110,8 @@ export function ChartContainer({
107110
(legendBottomMaxHeight ? <div style={{ maxHeight: `${legendBottomMaxHeight}px` }}>{legend}</div> : legend)}
108111
{footer}
109112
</div>
113+
114+
{!legend || legendPosition === "bottom" ? noData : null}
110115
</div>
111116
);
112117
}

src/core/chart-core.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { VerticalAxisTitle } from "./components/core-vertical-axis-title";
2626
import { getFormatter } from "./formatters";
2727
import { useChartI18n } from "./i18n-utils";
2828
import { CoreChartProps } from "./interfaces";
29-
import { getPointAccessibleDescription } from "./utils";
29+
import { getPointAccessibleDescription, hasVisibleLegendItems } from "./utils";
3030

3131
import styles from "./styles.css.js";
3232
import testClasses from "./test-classes/styles.css.js";
@@ -302,7 +302,7 @@ export function InternalCoreChart({
302302
}}
303303
navigator={navigator}
304304
legend={
305-
context.legendEnabled ? (
305+
context.legendEnabled && hasVisibleLegendItems(options) ? (
306306
<ChartLegend
307307
{...legendOptions}
308308
position={legendPosition}
@@ -328,6 +328,7 @@ export function InternalCoreChart({
328328
/>
329329
) : null
330330
}
331+
noData={context.noDataEnabled && <ChartNoData {...noDataOptions} i18nStrings={i18nStrings} api={api} />}
331332
/>
332333

333334
{context.tooltipEnabled && (
@@ -338,8 +339,6 @@ export function InternalCoreChart({
338339
api={api}
339340
/>
340341
)}
341-
342-
{context.noDataEnabled && <ChartNoData {...noDataOptions} i18nStrings={i18nStrings} api={api} />}
343342
</div>
344343
);
345344
}

src/core/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ $side-legend-min-inline-size: max(20%, 150px);
108108
}
109109

110110
.chart-plot-wrapper {
111+
position: relative;
111112
flex: 1;
112113
}
113114

src/core/utils.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,21 @@ export function getChartLegendItems(chart: Highcharts.Chart): readonly LegendIte
170170
return legendItems;
171171
}
172172

173+
export function hasVisibleLegendItems(options: Highcharts.Options) {
174+
return !!options.series?.some((series) => {
175+
// The pie series is not shown in the legend, but their segments are always shown.
176+
if (series.type === "pie") {
177+
return Array.isArray(series.data) && series.data.length > 0;
178+
}
179+
// We only support errorbar series that are linked to other series. Those are not represented separately
180+
// in the legend, but can be controlled from the outside, using controllable items visibility API.
181+
if (series.type === "errorbar") {
182+
return false;
183+
}
184+
return series.showInLegend !== false;
185+
});
186+
}
187+
173188
// This function returns coordinates of a rectangle, including the target point.
174189
// There are differences in how the rectangle is computed, but in all cases it is supposed to
175190
// enclose the point's visual representation in the chart, with no extra offsets.

0 commit comments

Comments
 (0)