Skip to content

Commit bd169c5

Browse files
committed
refactor: chart legend API with more semantic types
1 parent 97c27f6 commit bd169c5

File tree

4 files changed

+31
-48
lines changed

4 files changed

+31
-48
lines changed

src/core/chart-core.tsx

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import Spinner from "@cloudscape-design/components/spinner";
1313
import { getDataAttributes } from "../internal/base-component/get-data-attributes";
1414
import { InternalBaseComponentProps } from "../internal/base-component/use-base-component";
1515
import * as Styles from "../internal/chart-styles";
16-
import { ChartLegendType } from "../internal/components/chart-legend";
1716
import { castArray } from "../internal/utils/utils";
1817
import { useChartAPI } from "./chart-api";
1918
import { ChartContainer } from "./chart-container";
@@ -32,19 +31,6 @@ import { getPointAccessibleDescription, hasVisibleLegendItems } from "./utils";
3231
import styles from "./styles.css.js";
3332
import testClasses from "./test-classes/styles.css.js";
3433

35-
function getLegendType(options: CoreChartProps.LegendOptions, isSecondaryLegend: boolean = false): ChartLegendType {
36-
switch (options.type) {
37-
case "single":
38-
return options.position === "side" ? "stacked" : "bottom";
39-
case "dual":
40-
if (options.position === "side") {
41-
return isSecondaryLegend ? "stacked-bottom" : "stacked-top";
42-
}
43-
return isSecondaryLegend ? "bottom-right" : "bottom-left";
44-
}
45-
return "bottom";
46-
}
47-
4834
/**
4935
* CoreChart is the core internal abstraction that accepts the entire set of Highcharts options along
5036
* with Cloudscape props to define custom tooltip, no-data, formatters, items visibility, and more.
@@ -318,8 +304,9 @@ export function InternalCoreChart({
318304
primaryLegend={
319305
context.legendEnabled && hasVisibleLegendItems(options) ? (
320306
<ChartLegend
321-
type={legendOptions ? getLegendType(legendOptions) : "bottom"}
322307
api={api}
308+
type={legendOptions?.type === "single" ? "single" : "primary"}
309+
alignment={legendOptions?.position === "side" ? "vertical" : "horizontal"}
323310
i18nStrings={i18nStrings}
324311
title={legendOptions?.title}
325312
actions={legendOptions?.actions}
@@ -331,8 +318,9 @@ export function InternalCoreChart({
331318
secondaryLegend={
332319
context.legendEnabled && legendOptions && legendOptions.type === "dual" ? (
333320
<ChartLegend
334-
type={getLegendType(legendOptions, true)}
335321
api={api}
322+
type={"secondary"}
323+
alignment={legendOptions?.position === "side" ? "vertical" : "horizontal"}
336324
i18nStrings={i18nStrings}
337325
title={legendOptions.secondaryLegendTitle}
338326
actions={legendOptions.actions}

src/core/components/core-legend.tsx

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,25 @@
33

44
import { useInternalI18n } from "@cloudscape-design/components/internal/do-not-use/i18n";
55

6-
import { ChartLegend as ChartLegendComponent, ChartLegendType } from "../../internal/components/chart-legend";
7-
import { LegendItem } from "../../internal/components/interfaces";
6+
import { ChartLegend as ChartLegendComponent } from "../../internal/components/chart-legend";
87
import { fireNonCancelableEvent, NonCancelableEventHandler } from "../../internal/events";
98
import { useSelector } from "../../internal/utils/async-store";
109
import { ChartAPI } from "../chart-api";
1110
import { BaseI18nStrings, CoreChartProps } from "../interfaces";
1211

13-
function getFilteredItems(type: ChartLegendType, items: readonly LegendItem[]) {
14-
switch (type) {
15-
case "bottom":
16-
case "stacked":
17-
return items;
18-
case "bottom-left":
19-
case "stacked-top":
20-
return items.filter((item) => !item.oppositeAxis);
21-
case "bottom-right":
22-
case "stacked-bottom":
23-
return items.filter((item) => item.oppositeAxis);
24-
}
25-
return items;
26-
}
27-
2812
export function ChartLegend({
29-
type,
3013
api,
14+
type,
15+
alignment,
3116
title,
3217
actions,
3318
i18nStrings,
3419
onItemHighlight,
3520
getLegendTooltipContent,
3621
}: {
37-
type: ChartLegendType;
3822
api: ChartAPI;
23+
alignment: "horizontal" | "vertical";
24+
type: "single" | "primary" | "secondary";
3925
title?: string;
4026
actions?: React.ReactNode;
4127
i18nStrings?: BaseI18nStrings;
@@ -47,8 +33,13 @@ export function ChartLegend({
4733
const legendItems = useSelector(api.legendStore, (s) => s.items);
4834
const isChartTooltipPinned = useSelector(api.tooltipStore, (s) => s.pinned);
4935

50-
const filteredItems = getFilteredItems(type, legendItems);
5136
const someHighlighted = legendItems.some((item) => item.highlighted);
37+
const filteredItems =
38+
type === "single"
39+
? legendItems
40+
: type === "primary"
41+
? legendItems.filter((item) => !item.oppositeAxis)
42+
: legendItems.filter((item) => item.oppositeAxis);
5243

5344
const onToggleItem = (itemId: string) => {
5445
const visibleItems = legendItems.filter((i) => i.visible).map((i) => i.id);
@@ -78,6 +69,7 @@ export function ChartLegend({
7869
return (
7970
<ChartLegendComponent
8071
type={type}
72+
alignment={alignment}
8173
ariaLabel={ariaLabel}
8274
legendTitle={title}
8375
items={filteredItems}

src/internal-do-not-use/core-legend/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ export const CoreLegend = ({
1616
onVisibleItemsChange,
1717
getLegendTooltipContent,
1818
}: CoreLegendProps) => {
19-
const type = alignment === "horizontal" ? "bottom" : "stacked";
20-
2119
const onToggleItem = (itemId: string) => {
2220
const visibleItems = items.filter((i) => i.visible).map((i) => i.id);
2321
if (visibleItems.includes(itemId)) {
@@ -50,8 +48,9 @@ export const CoreLegend = ({
5048

5149
return (
5250
<ChartLegendComponent
53-
type={type}
5451
items={items}
52+
type={"single"}
53+
alignment={alignment}
5554
actions={actions}
5655
legendTitle={title}
5756
ariaLabel={ariaLabel}

src/internal/components/chart-legend/index.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,11 @@ const HIGHLIGHT_LOST_DELAY = 50;
2828
const SCROLL_DELAY = 100;
2929
const SHOULD_STACK_SIZE = 400;
3030

31-
export type ChartLegendType = "bottom" | "stacked" | "stacked-top" | "stacked-bottom" | "bottom-left" | "bottom-right";
32-
3331
export interface ChartLegendProps {
34-
type: ChartLegendType;
3532
someHighlighted: boolean;
3633
items: readonly LegendItem[];
34+
alignment: "horizontal" | "vertical";
35+
type: "single" | "primary" | "secondary";
3736
legendTitle?: string;
3837
ariaLabel?: string;
3938
actions?: React.ReactNode;
@@ -45,8 +44,9 @@ export interface ChartLegendProps {
4544
}
4645

4746
export const ChartLegend = ({
48-
type,
4947
items,
48+
type,
49+
alignment,
5050
someHighlighted,
5151
legendTitle,
5252
ariaLabel,
@@ -57,7 +57,7 @@ export const ChartLegend = ({
5757
onItemHighlightExit,
5858
getTooltipContent,
5959
}: ChartLegendProps) => {
60-
const [shouldStack, containerQueryRef] = useContainerQuery((rect) => rect.borderBoxWidth <= SHOULD_STACK_SIZE);
60+
const [shouldAutoStack, containerQueryRef] = useContainerQuery((rect) => rect.borderBoxWidth <= SHOULD_STACK_SIZE);
6161
const containerRef = containerQueryRef as React.RefObject<HTMLDivElement>;
6262
const elementsByIndexRef = useRef<Record<number, HTMLElement>>([]);
6363
const elementsByIdRef = useRef<Record<string, HTMLElement>>({});
@@ -210,8 +210,8 @@ export const ChartLegend = ({
210210
navigationAPI.current!.updateFocusTarget();
211211
});
212212

213-
const isStacked = type.startsWith("stacked") || shouldStack;
214-
const isBottomRightNotStacked = type === "bottom-right" && !shouldStack;
213+
const isStacked = alignment === "vertical" || shouldAutoStack;
214+
const isHorizontalSecondaryAndNotStacked = alignment === "horizontal" && type === "secondary" && !shouldAutoStack;
215215

216216
const tooltipTrack = useRef<null | HTMLElement>(null);
217217
const tooltipTarget = items.find((item) => item.id === tooltipItemId) ?? null;
@@ -234,7 +234,11 @@ export const ChartLegend = ({
234234
onMouseLeave={() => (isMouseInContainer.current = false)}
235235
>
236236
{legendTitle && (
237-
<Box fontWeight="bold" textAlign={isBottomRightNotStacked ? "right" : "left"} className={testClasses.title}>
237+
<Box
238+
fontWeight="bold"
239+
className={testClasses.title}
240+
textAlign={isHorizontalSecondaryAndNotStacked ? "right" : "left"}
241+
>
238242
{legendTitle}
239243
</Box>
240244
)}
@@ -246,7 +250,7 @@ export const ChartLegend = ({
246250
className={clsx(styles.list, {
247251
[styles["list-side"]]: isStacked,
248252
[styles["list-bottom"]]: !isStacked,
249-
[styles["list-bottom-secondary"]]: isBottomRightNotStacked,
253+
[styles["list-bottom-secondary"]]: isHorizontalSecondaryAndNotStacked,
250254
})}
251255
>
252256
{actions && (

0 commit comments

Comments
 (0)