Skip to content
Draft
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
111 changes: 111 additions & 0 deletions pages/05-demos/with-split-panel.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { useState } from "react";

import Button from "@cloudscape-design/components/button";
import ColumnLayout from "@cloudscape-design/components/column-layout";
import Container from "@cloudscape-design/components/container";
import Link from "@cloudscape-design/components/link";
import SplitPanel from "@cloudscape-design/components/split-panel";

import { CartesianChart, PieChart } from "../../lib/components";
import { moneyFormatter } from "../common/formatters";
import { PageSettings, useChartSettings } from "../common/page-settings";
import { Page } from "../common/templates";

interface ThisPageSettings extends PageSettings {
visibleItems: string;
}

const categories = ["Jun 2019", "Jul 2019", "Aug 2019", "Sep 2019", "Oct 2019", "Nov 2019", "Dec 2019"];

export default function () {
const [splitPanelContent, setSplitPanelContent] = useState("");
const chartSplitPanelProps = {
onToggle: (content: string) => setSplitPanelContent((prev) => (prev === content ? "" : content)),
};
return (
<Page
title="Chart with split panel demo"
subtitle="This page demonstrates opening a split panel from inside chart's tooltip."
splitPanel={<SplitPanel header="Details">{splitPanelContent}</SplitPanel>}
splitPanelOpen={splitPanelContent !== ""}
splitPanelPreferences={{ position: "side" }}
onSplitPanelToggle={() => setSplitPanelContent((prev) => (prev ? "" : "generic content"))}
>
<Container>
<ColumnLayout columns={2}>
<LineChartDemo splitPanel={chartSplitPanelProps} />
<PieChartDemo splitPanel={chartSplitPanelProps} />
</ColumnLayout>
</Container>
</Page>
);
}

function LineChartDemo({ splitPanel }: { splitPanel: { onToggle: (content: string) => void } }) {
const { chartProps } = useChartSettings<ThisPageSettings>();
return (
<CartesianChart
{...chartProps.cartesian}
chartHeight={200}
ariaLabel="Mixed bar chart"
legend={{ enabled: false }}
series={[
{
id: "Costs",
name: "Costs",
type: "line",
data: [6562, 8768, 9742, 10464, 16777, 9956, 5876],
},
]}
tooltip={{
point: ({ item }) => {
return {
key: item.series.name,
value: (
<Link external={true} href="#" ariaLabel={`See details for ${item.series.name} (opens in a new tab)`}>
{item.y !== null ? moneyFormatter(item.y) : null}
</Link>
),
};
},
footer: (detail) => (
<Button onClick={() => splitPanel.onToggle(`Line chart point, x=${detail.x}`)}>Toggle details</Button>
),
}}
xAxis={{ title: "", type: "category", categories }}
yAxis={{ title: "" }}
/>
);
}

function PieChartDemo({ splitPanel }: { splitPanel: { onToggle: (content: string) => void } }) {
const { chartProps } = useChartSettings<ThisPageSettings>();
return (
<PieChart
{...chartProps.pie}
chartHeight={200}
ariaLabel="Pie chart"
legend={{ enabled: false }}
segmentTitle={() => ""}
tooltip={{
footer: (detail) => (
<Button onClick={() => splitPanel.onToggle(`Pie chart point, segment=${detail.segmentName}`)}>
Toggle details
</Button>
),
}}
series={{
name: "Resource count",
type: "pie",
data: [
{ name: "Running", y: 60 },
{ name: "Failed", y: 30 },
{ name: "In-progress", y: 10 },
],
}}
/>
);
}
12 changes: 12 additions & 0 deletions pages/common/templates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,20 @@ export function Page({
settings,
children,
screenshotArea = true,
splitPanel,
splitPanelOpen,
splitPanelPreferences,
onSplitPanelToggle,
}: {
title: React.ReactNode;
subtitle?: React.ReactNode;
settings?: React.ReactNode;
children: React.ReactNode;
screenshotArea?: boolean;
splitPanel?: React.ReactNode;
splitPanelOpen?: boolean;
splitPanelPreferences?: AppLayoutProps.SplitPanelPreferences;
onSplitPanelToggle?: () => void;
}) {
const { urlParams } = useContext(AppContext);
const [toolsOpen, setToolsOpen] = useState(!urlParams.screenshotMode);
Expand All @@ -77,6 +85,10 @@ export function Page({
activeDrawerId={toolsOpen ? "settings" : null}
onDrawerChange={({ detail }) => setToolsOpen(!!detail.activeDrawerId)}
drawers={drawers}
splitPanelOpen={splitPanelOpen}
onSplitPanelToggle={onSplitPanelToggle}
splitPanelPreferences={splitPanelPreferences}
splitPanel={splitPanel}
content={
<Box>
<h1>{title}</h1>
Expand Down
13 changes: 13 additions & 0 deletions src/core/chart-api/chart-extra-tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export class ChartExtraTooltip extends AsyncStore<ReactiveTooltipState> {
private targetTrack = new SVGRendererSingle();
private groupTrack = new SVGRendererSingle();

// Cached coordinates to update cursor's position on re-render.
private lastPoint: null | Highcharts.Point = null;
private lastGroup: null | readonly Highcharts.Point[] = null;

constructor(context: ChartExtraContext) {
super({ visible: false, pinned: false, point: null, group: [] });
this.context = context;
Expand All @@ -63,6 +67,12 @@ export class ChartExtraTooltip extends AsyncStore<ReactiveTooltipState> {
public getTargetTrack = () => (this.targetTrack.element?.element ?? null) as null | SVGElement;
public getGroupTrack = () => (this.groupTrack.element?.element ?? null) as null | SVGElement;

public onChartRender() {
if (this.lastGroup && this.get().visible) {
this.updateTooltipCursor({ point: this.lastPoint, group: this.lastGroup });
}
}

public onChartDestroy() {
this.cursor.destroy();
this.targetTrack.destroy();
Expand Down Expand Up @@ -111,6 +121,9 @@ export class ChartExtraTooltip extends AsyncStore<ReactiveTooltipState> {
}

private updateTooltipCursor = (props: { point: null | Highcharts.Point; group: readonly Highcharts.Point[] }) => {
this.lastPoint = props.point;
this.lastGroup = props.group;

const chartType =
this.context.chart().series.find((s) => s.type === "pie" || s.type === "solidgauge")?.type ?? "cartesian";
if (chartType === "pie") {
Expand Down
1 change: 1 addition & 0 deletions src/core/chart-api/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export class ChartAPI {
chartAPI.chartExtraLegend.onChartRender();
chartAPI.chartExtraNodata.onChartRender();
chartAPI.chartExtraAxisTitles.onChartRender();
chartAPI.chartExtraTooltip.onChartRender();
chartAPI.handleDestroyedPoints();
chartAPI.resetColorCounter();
chartAPI.showMarkersForIsolatedPoints();
Expand Down
Loading