diff --git a/pages/03-core/core-legend-horizontal-alignment.page.tsx b/pages/03-core/core-legend-horizontal-alignment.page.tsx
new file mode 100644
index 00000000..19367574
--- /dev/null
+++ b/pages/03-core/core-legend-horizontal-alignment.page.tsx
@@ -0,0 +1,165 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { omit } from "lodash";
+
+import ColumnLayout from "@cloudscape-design/components/column-layout";
+import SpaceBetween from "@cloudscape-design/components/space-between";
+
+import { CoreChartProps } from "../../lib/components/core/interfaces";
+import CoreChart from "../../lib/components/internal-do-not-use/core-chart";
+import { PageSettingsForm, useChartSettings } from "../common/page-settings";
+import { Page } from "../common/templates";
+import pseudoRandom from "../utils/pseudo-random";
+
+function randomInt(min: number, max: number) {
+ return min + Math.floor(pseudoRandom() * (max - min));
+}
+
+const lineChartData = [
+ { x: 1600984800000, y: 58020 },
+ { x: 1600985700000, y: 102402 },
+ { x: 1600986600000, y: 104920 },
+ { x: 1600987500000, y: 94031 },
+ { x: 1600988400000, y: 125021 },
+ { x: 1600989300000, y: 159219 },
+ { x: 1600990200000, y: 193082 },
+ { x: 1600991100000, y: 162592 },
+ { x: 1600992000000, y: 274021 },
+ { x: 1600992900000, y: 264286 },
+ { x: 1600993800000, y: 289210 },
+ { x: 1600994700000, y: 256362 },
+ { x: 1600995600000, y: 257306 },
+ { x: 1600996500000, y: 186776 },
+ { x: 1600997400000, y: 294020 },
+ { x: 1600998300000, y: 385975 },
+ { x: 1600999200000, y: 486039 },
+ { x: 1601000100000, y: 490447 },
+ { x: 1601001000000, y: 361845 },
+ { x: 1601001900000, y: 339058 },
+ { x: 1601002800000, y: 298028 },
+ { x: 1601003400000, y: 255555 },
+ { x: 1601003700000, y: 231902 },
+ { x: 1601004600000, y: 224558 },
+ { x: 1601005500000, y: 253901 },
+ { x: 1601006400000, y: 102839 },
+ { x: 1601007300000, y: 234943 },
+ { x: 1601008200000, y: 204405 },
+ { x: 1601009100000, y: 190391 },
+ { x: 1601010000000, y: 183570 },
+ { x: 1601010900000, y: 162592 },
+ { x: 1601011800000, y: 148910 },
+];
+
+export default function () {
+ const { chartProps } = useChartSettings({ solidgauge: true });
+
+ const charts: ((horizontalAlignment: CoreChartProps.LegendOptionsHorizontalAlignment) => CoreChartProps)[] = [
+ (horizontalAlignment) => ({
+ ...omit(chartProps.cartesian, "ref"),
+ legend: {
+ horizontalAlignment,
+ title: chartProps.cartesian.legend?.title,
+ actions: chartProps.cartesian.legend?.actions,
+ },
+ options: {
+ chart: {
+ type: "pie",
+ },
+ title: {
+ text: `${horizontalAlignment} aligned Pie`,
+ },
+ yAxis: {
+ min: 0,
+ max: 100,
+ title: {
+ text: "Usage",
+ },
+ },
+ series: [
+ {
+ name: "Storage Distribution",
+ type: "pie",
+ data: [
+ { y: randomInt(30, 40), name: "Documents" },
+ { y: randomInt(20, 30), name: "Images" },
+ { y: randomInt(15, 25), name: "Videos" },
+ { y: randomInt(10, 15), name: "Other" },
+ ],
+ },
+ ],
+ },
+ }),
+ (horizontalAlignment) => ({
+ ...omit(chartProps.cartesian, "ref"),
+ legend: {
+ horizontalAlignment,
+ title: chartProps.cartesian.legend?.title,
+ actions: chartProps.cartesian.legend?.actions,
+ },
+ options: {
+ chart: {
+ type: "solidgauge",
+ },
+ title: {
+ text: `${horizontalAlignment} aligned Gauge`,
+ },
+ yAxis: {
+ min: 0,
+ max: 100,
+ },
+ series: [
+ {
+ type: "solidgauge",
+ name: "Download speed",
+ data: [randomInt(50, 100)],
+ showInLegend: true,
+ dataLabels: {
+ format: "{y} MB/s",
+ },
+ },
+ ],
+ },
+ }),
+ (horizontalAlignment) => ({
+ ...omit(chartProps.cartesian, "ref"),
+ legend: {
+ horizontalAlignment,
+ title: chartProps.cartesian.legend?.title,
+ actions: chartProps.cartesian.legend?.actions,
+ },
+ options: {
+ chart: {
+ type: "line",
+ },
+ title: {
+ text: `${horizontalAlignment} aligned Line`,
+ },
+ series: [
+ {
+ type: "line",
+ name: "Download speed",
+ data: lineChartData,
+ },
+ ],
+ },
+ }),
+ ];
+
+ return (
+ }
+ >
+
+ {charts.map((chart, i) => (
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/pages/03-core/core-line-chart.page.tsx b/pages/03-core/core-line-chart.page.tsx
index a7d8bb6d..b2864dbd 100644
--- a/pages/03-core/core-line-chart.page.tsx
+++ b/pages/03-core/core-line-chart.page.tsx
@@ -91,7 +91,14 @@ export default function () {
subtitle="The page demonstrates the use of the core chart, including additional legend settings."
settings={
}
>
diff --git a/pages/common/page-settings.tsx b/pages/common/page-settings.tsx
index dafd6e16..9c575b92 100644
--- a/pages/common/page-settings.tsx
+++ b/pages/common/page-settings.tsx
@@ -15,6 +15,7 @@ import Select from "@cloudscape-design/components/select";
import SpaceBetween from "@cloudscape-design/components/space-between";
import { CartesianChartProps, PieChartProps } from "../../lib/components";
+import { CoreChartProps } from "../../src/core/interfaces";
import AppContext, { AppContextType } from "../app/app-context";
import { useHighcharts } from "./use-highcharts";
@@ -36,6 +37,7 @@ export interface PageSettings {
showLegendActions: boolean;
legendBottomMaxHeight?: number;
legendPosition: "bottom" | "side";
+ legendHorizontalAlign: CoreChartProps.LegendOptionsHorizontalAlignment;
showCustomHeader: boolean;
showHeaderFilter: boolean;
showCustomFooter: boolean;
@@ -60,6 +62,7 @@ const DEFAULT_SETTINGS: PageSettings = {
showLegend: true,
showLegendTitle: false,
legendPosition: "bottom",
+ legendHorizontalAlign: "start",
showLegendActions: false,
showCustomHeader: false,
showHeaderFilter: false,
@@ -150,7 +153,8 @@ export function useChartSettings : undefined,
position: settings.legendPosition,
bottomMaxHeight: settings.legendBottomMaxHeight,
- };
+ horizontalAlignment: settings.legendHorizontalAlign,
+ } satisfies CoreChartProps.LegendOptions;
return {
settings,
setSettings,
@@ -388,6 +392,32 @@ export function PageSettingsForm({
}
/>
);
+ case "legendHorizontalAlign":
+ return (
+
+ setSettings({
+ legendHorizontalAlign: detail.selectedId as CoreChartProps.LegendOptionsHorizontalAlignment,
+ })
+ }
+ />
+ );
case "showCustomHeader":
return (
;
getLegendTooltipContent?: CoreChartProps.GetLegendTooltipContent;
@@ -39,6 +41,7 @@ export function ChartLegend({
ariaLabel={ariaLabel}
legendTitle={title}
items={legendItems}
+ horizontalAlignment={horizontalAlignment}
actions={actions}
position={position}
onItemVisibilityChange={api.onItemVisibilityChange}
diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts
index e299768e..9401bd7b 100644
--- a/src/core/interfaces.ts
+++ b/src/core/interfaces.ts
@@ -420,7 +420,14 @@ export namespace CoreChartProps {
export interface LegendOptions extends BaseLegendOptions {
bottomMaxHeight?: number;
position?: "bottom" | "side";
+ /**
+ * This property only applies when `position="bottom"`.
+ */
+ horizontalAlignment?: LegendOptionsHorizontalAlignment;
}
+
+ export type LegendOptionsHorizontalAlignment = "start" | "center";
+
export type LegendItem = InternalComponentTypes.LegendItem;
export type LegendTooltipContent = InternalComponentTypes.LegendTooltipContent;
export type GetLegendTooltipContent = InternalComponentTypes.GetLegendTooltipContent;
@@ -488,6 +495,7 @@ export interface CoreLegendProps {
ariaLabel?: string;
actions?: React.ReactNode;
alignment?: "horizontal" | "vertical";
+ horizontalAlignment?: CoreChartProps.LegendOptionsHorizontalAlignment;
onClearHighlight?: NonCancelableEventHandler;
onItemHighlight?: NonCancelableEventHandler;
onVisibleItemsChange?: NonCancelableEventHandler;
diff --git a/src/internal-do-not-use/core-legend/index.tsx b/src/internal-do-not-use/core-legend/index.tsx
index 43663abc..263856e7 100644
--- a/src/internal-do-not-use/core-legend/index.tsx
+++ b/src/internal-do-not-use/core-legend/index.tsx
@@ -15,6 +15,7 @@ export const CoreLegend = ({
onClearHighlight,
onVisibleItemsChange,
getLegendTooltipContent,
+ horizontalAlignment = "start",
}: CoreLegendProps) => {
const position = alignment === "horizontal" ? "bottom" : "side";
@@ -28,6 +29,7 @@ export const CoreLegend = ({
actions={actions}
legendTitle={title}
position={position}
+ horizontalAlignment={horizontalAlignment}
ariaLabel={ariaLabel}
getTooltipContent={(props) => getLegendTooltipContent?.(props) ?? null}
onItemHighlightExit={() => fireNonCancelableEvent(onClearHighlight)}
diff --git a/src/internal/components/chart-legend/index.tsx b/src/internal/components/chart-legend/index.tsx
index d6b4e148..93cead88 100644
--- a/src/internal/components/chart-legend/index.tsx
+++ b/src/internal/components/chart-legend/index.tsx
@@ -16,6 +16,7 @@ import {
import Box from "@cloudscape-design/components/box";
import { InternalChartTooltip } from "@cloudscape-design/components/internal/do-not-use/chart-tooltip";
+import { CoreChartProps } from "../../../core/interfaces";
import { DebouncedCall } from "../../utils/utils";
import { GetLegendTooltipContentProps, LegendItem, LegendTooltipContent } from "../interfaces";
@@ -32,6 +33,7 @@ export interface ChartLegendProps {
ariaLabel?: string;
actions?: React.ReactNode;
position: "bottom" | "side";
+ horizontalAlignment: CoreChartProps.LegendOptionsHorizontalAlignment;
onItemHighlightEnter: (item: LegendItem) => void;
onItemHighlightExit: () => void;
onItemVisibilityChange: (hiddenItems: string[]) => void;
@@ -48,6 +50,7 @@ export const ChartLegend = ({
onItemHighlightEnter,
onItemHighlightExit,
getTooltipContent,
+ horizontalAlignment,
}: ChartLegendProps) => {
const containerRef = useRef(null);
const elementsByIndexRef = useRef>([]);
@@ -246,7 +249,12 @@ export const ChartLegend = ({
onMouseLeave={() => (isMouseInContainer.current = false)}
>
{legendTitle && (
-
+
{legendTitle}
)}
@@ -256,6 +264,7 @@ export const ChartLegend = ({
// Setting the tab index to -1 does fix the problem.
tabIndex={-1}
className={clsx(styles.list, {
+ [styles[`list-bottom-${horizontalAlignment}`]]: position === "bottom",
[styles["list-bottom"]]: position === "bottom",
[styles["list-side"]]: position === "side",
})}
@@ -280,6 +289,7 @@ export const ChartLegend = ({
)}