Skip to content

Commit

Permalink
feat: add Treemap viz
Browse files Browse the repository at this point in the history
  • Loading branch information
plagoa authored and MEsteves22 committed Apr 16, 2024
1 parent b0e3595 commit f92a418
Show file tree
Hide file tree
Showing 11 changed files with 3,085 additions and 12 deletions.
1 change: 1 addition & 0 deletions .storybook/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const excludeStories = [
"Visualizations/Donut Chart",
"Visualizations/Confusion Matrix",
"Visualizations/Scatter Plot",
"Visualizations/Treemap Chart",
"Widgets/Code Editor",
];

Expand Down
83 changes: 83 additions & 0 deletions packages/viz/src/Treemap/Treemap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { forwardRef } from "react";
import ReactECharts from "echarts-for-react/lib/core";
import { TreemapChart } from "echarts/charts";
import { TooltipComponent } from "echarts/components";
import * as echarts from "echarts/core";

import { HvBaseChart } from "../BaseChart";
import { HvChartTooltipClasses, useOption, useTooltip } from "../hooks";
import { HvChartTooltip } from "../types";
import { HvChartCommonProps } from "../types/common";
import { HvTreemapData } from "../types/generic";

// Register chart components
echarts.use([TreemapChart, TooltipComponent]);

export interface HvTreemapChartClasses extends HvChartTooltipClasses {}

export interface HvTreemapChartProps
extends Omit<
HvChartCommonProps,
"data" | "groupBy" | "sortBy" | "grid" | "legend" | "tooltip"
> {
/** The name of the treemap */
name?: string;
/** The data to use on the treemap */
data?: HvTreemapData[];
/** The tooltip options. */
tooltip?: Omit<HvChartTooltip, "type">;
/** A Jss Object used to override or extend the styles applied to the component. */
classes?: HvTreemapChartClasses;
}

/**
* A tree map chart visually represents hierarchical data using nested rectangles, with each rectangle's size proportional to the value it represents.
*/
export const HvTreemapChart = forwardRef<ReactECharts, HvTreemapChartProps>(
(props, ref) => {
const {
name,
data,
classes,
width,
height,
tooltip,
onOptionChange,
...others
} = props;

const chartTooltip = useTooltip({
...tooltip,
type: "single",
classes,
});

const option = useOption({
option: {
title: {
text: name,
left: "center",
},
series: [
{
name,
type: "treemap",
data,
},
],
...chartTooltip,
},
onOptionChange,
});

return (
<HvBaseChart
ref={ref}
option={option}
width={width}
height={height}
{...others}
/>
);
},
);
1 change: 1 addition & 0 deletions packages/viz/src/Treemap/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Treemap";
99 changes: 99 additions & 0 deletions packages/viz/src/Treemap/stories/CustomTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { css, cx } from "@emotion/css";
import { theme } from "@hitachivantara/uikit-react-core";
import {
HvChartTooltipParams,
HvTreemapChart,
} from "@hitachivantara/uikit-react-viz";

import { data as testData } from "./data";

const styles = {
root: css({
display: "flex",
flexDirection: "column",
backgroundColor: theme.colors.atmo1,
width: "fit-content",
minWidth: 220,
boxShadow: theme.colors.shadow,
}),
container: css({
padding: theme.spacing("15px", "sm"),
display: "flex",
flexDirection: "column",
}),
containerBorder: css({
borderBottom: `3px solid ${theme.colors.atmo2}`,
}),
valuesContainer: css({
display: "flex",
gap: 8,
justifyContent: "space-between",
alignItems: "center",
width: "100%",
}),
title: css({
marginBottom: 10,
}),
separator: css({
marginRight: theme.space.md,
}),
thresholdContainer: css({
display: "flex",
alignItems: "center",
"& > div": {
width: 24,
height: 24,
"& > svg": {
marginLeft: 0,
},
},
}),
label: css({
fontFamily: theme.fontFamily.body,
fontWeight: theme.fontWeights.semibold,
fontSize: theme.fontSizes.sm,
color: theme.colors.secondary,
}),
color: css({
display: "flex",
width: 12,
height: 12,
padding: 4,
border: `1px solid ${theme.colors.secondary}`,
}),
};

const renderTooltip = (params?: HvChartTooltipParams) => {
return `
<div class="${styles.root}">
<div class="${cx(styles.container, styles.containerBorder)}">
<div>
<p class="${styles.label}">${params?.title}</p>
</div>
</div>
<div class="${cx(styles.container, styles.containerBorder)}">
<div class="${cx(styles.valuesContainer, styles.title)}">
<div class="${styles.color}" style="background-color: ${params?.series?.[0].color}"></div>
<div class="${cx(styles.label, styles.separator)}">
${params?.series?.[0].name}
</div>
<div class="${styles.thresholdContainer}">
${params?.series?.[0].value}
</div>
</div>
</div>
</div>`;
};

export const CustomTooltip = () => {
return (
<HvTreemapChart
name="Public Spending"
data={testData}
tooltip={{
show: true,
component: renderTooltip,
}}
/>
);
};
107 changes: 107 additions & 0 deletions packages/viz/src/Treemap/stories/Treemap.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { Meta, StoryObj } from "@storybook/react";
import {
HvTreemapChart,
HvTreemapChartProps,
} from "@hitachivantara/uikit-react-viz";

import { vizDecorator } from "../../BaseChart/stories/utils";
import { CustomTooltip as CustomTooltipStory } from "./CustomTooltip";
import CustomTooltipRaw from "./CustomTooltip?raw";
import { data as testData } from "./data";

const meta: Meta<typeof HvTreemapChart> = {
title: "Visualizations/Treemap Chart",
component: HvTreemapChart,
decorators: [vizDecorator],
};
export default meta;

export const Main: StoryObj<HvTreemapChartProps> = {
args: {},
argTypes: {
data: { control: { disable: true } },
tooltip: { control: { disable: true } },
classes: { control: { disable: true } },
},
render: ({ data, ...others }) => {
return (
<HvTreemapChart name="Public Spending" data={testData} {...others} />
);
},
};

export const CustomTooltip: StoryObj<HvTreemapChartProps> = {
parameters: {
docs: {
description: {
story:
"This sample illustrates how to change the default tooltip to a custom one.",
},
source: { code: CustomTooltipRaw },
},
},
render: () => <CustomTooltipStory />,
};

export const CustomEchartsOptions: StoryObj<HvTreemapChartProps> = {
parameters: {
docs: {
description: {
story:
"If necessary, you can customize the chart's option and take advantage of the additional properties offered by ECharts. In this sample we change some of the visual styles of the Treemap",
},
},
},
render: ({ data, ...others }) => {
return (
<HvTreemapChart
name="Public Spending"
data={testData}
onOptionChange={(option) => {
option.series = {
...option.series[0],
visibleMin: 1000,
upperLabel: {
show: true,
height: 20,
},
levels: [
{
itemStyle: {
borderColor: "#777",
borderWidth: 0,
gapWidth: 1,
},
upperLabel: {
show: false,
},
},
{
itemStyle: {
borderColor: "#555",
borderWidth: 5,
gapWidth: 1,
},
emphasis: {
itemStyle: {
borderColor: "#ddd",
},
},
},
{
colorSaturation: [0.35, 0.5],
itemStyle: {
borderWidth: 5,
gapWidth: 1,
borderColorSaturation: 0.6,
},
},
],
};
return option;
}}
{...others}
/>
);
},
};

0 comments on commit f92a418

Please sign in to comment.