From 26b7662b9e293c14576b81625b57b595fc21bafc Mon Sep 17 00:00:00 2001 From: e26chiu Date: Tue, 13 Dec 2022 22:21:00 -0500 Subject: [PATCH] Fix GroupBarGraph component --- components/GroupedBarGraph.module.css | 2 + components/GroupedBarGraph.tsx | 137 +++++++++----------------- 2 files changed, 51 insertions(+), 88 deletions(-) diff --git a/components/GroupedBarGraph.module.css b/components/GroupedBarGraph.module.css index 96ab995..4e6dcd0 100644 --- a/components/GroupedBarGraph.module.css +++ b/components/GroupedBarGraph.module.css @@ -1,5 +1,6 @@ .wrapper { display: flex; + flex-direction: column; align-items: center; width: min-content; } @@ -35,4 +36,5 @@ .legend { display: flex; margin: calc(16rem / 16); + justify-content: center; } diff --git a/components/GroupedBarGraph.tsx b/components/GroupedBarGraph.tsx index 28ef034..bce8fdf 100644 --- a/components/GroupedBarGraph.tsx +++ b/components/GroupedBarGraph.tsx @@ -49,7 +49,18 @@ interface GroupedBarGraphProps { valueAxisLabelSize?: number; /** Controls the distance between the value axis label and the value axis. */ valueAxisLabelOffset?: number; - legendProps?: LegendProps; + /** Margin for each item in the legend */ + itemMargin?: string; + /** Minimum width of the graph. */ + minWidth?: number; + /** Breakpoint width of graph where alernating labels are displayed. Only for Vertical graphs */ + widthAlternatingLabel?: number; + /** Space added to the bottom of the graph to show overflowing labels. Only for Vertical graphs */ + alternatingLabelSpace?: number; + /** Default position of labels in x-axis, in px. */ + defaultLabelDy?: string; + /** Position of lower labels in x-axis, in px. Only for Vertical graphs */ + lowerLabelDy?: string; } // Best format for props @@ -66,38 +77,21 @@ interface BarGroupData { [key: string]: string | number; } -interface LegendProps { - /** Position of the legend, relative to the graph. */ - position?: "top" | "right"; - /** Font size of the labels in the legend, in pixels. Default is 16px. */ - itemLabelSize?: number; - /** Gap between items in the legend, in pixels. */ - itemGap?: number; - /** Distance between the legend and other adjacent elements, in pixels. */ - margin?: { - top?: number; - bottom?: number; - left?: number; - right?: number; - }; -} - // BAR_PADDING must be in the range [0, 1) const BAR_PADDING = 0.2; const BAR_TEXT_PADDING = 12; const DEFAULT_LABEL_SIZE = 16; -const DEFAULT_LEGEND_GAP = 16; export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { const { data: propsData, barColors, barHoverColorsMap, - width, height, margin, className, + minWidth = 500, categoryTickLabelSize = DEFAULT_LABEL_SIZE, valueTickLabelSize = DEFAULT_LABEL_SIZE, hoverLabelSize, @@ -107,15 +101,17 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { valueAxisLabel, valueAxisLabelSize = DEFAULT_LABEL_SIZE, valueAxisLabelOffset = 0, - legendProps, + itemMargin = "0 0 0 15px", + widthAlternatingLabel = 600, + alternatingLabelSpace = 80, + defaultLabelDy = `0px`, + lowerLabelDy = `30px`, } = props; - - const { - position: legendPosition = "right", - itemLabelSize: legendLabelSize = DEFAULT_LABEL_SIZE, - itemGap: legendItemGap = DEFAULT_LEGEND_GAP, - margin: legendMargin = {}, - } = legendProps ?? {}; + const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth + const alternatingLabel = width <= widthAlternatingLabel; + const final_margin_bottom = alternatingLabel + ? margin.bottom + alternatingLabelSpace + : margin.bottom; const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => { return { category: datum.category, ...datum.values }; @@ -139,7 +135,7 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { .flat(); const categoryMax = width - margin.left - margin.right; - const valueMax = height - margin.top - margin.bottom; + const valueMax = height - margin.top - final_margin_bottom; const getCategory = (d: BarGroupData) => d.category; @@ -168,10 +164,15 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { return (
+
+ +
{Object.keys(barHoverColorsMap).map((color: string) => { @@ -256,11 +257,13 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { left={margin.left} hideAxisLine hideTicks - tickLabelProps={() => { + tickLabelProps={(value, index) => { + const alternatingDy = + index % 2 == 0 ? defaultLabelDy : lowerLabelDy; return { ...bottomTickLabelProps(), className: styles.tickLabel, - dy: "-0.25rem", + dy: alternatingLabel ? alternatingDy : defaultLabelDy, fontSize: `${categoryTickLabelSize / 16}rem`, width: categoryScale.bandwidth(), verticalAnchor: "start", @@ -297,27 +300,6 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) { }} /> -
); } @@ -327,10 +309,10 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) { data: propsData, barColors, barHoverColorsMap, - width, height, margin, className, + minWidth = 600, categoryTickLabelSize = DEFAULT_LABEL_SIZE, valueTickLabelSize = DEFAULT_LABEL_SIZE, hoverLabelSize, @@ -340,15 +322,10 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) { valueAxisLabel, valueAxisLabelSize = DEFAULT_LABEL_SIZE, valueAxisLabelOffset = 0, - legendProps, + itemMargin = "0 0 0 15px", + defaultLabelDy = "0", } = props; - - const { - position: legendPosition = "top", - itemLabelSize: legendLabelSize = DEFAULT_LABEL_SIZE, - itemGap: legendItemGap = DEFAULT_LEGEND_GAP, - margin: legendMargin = {}, - } = legendProps ?? {}; + const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => { return { category: datum.category, ...datum.values }; @@ -401,10 +378,15 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) { return (
+
+ +
{Object.keys(barHoverColorsMap).map((color: string) => { @@ -495,7 +477,7 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) { ...leftTickLabelProps(), className: styles.tickLabel, dx: "-0.5rem", - dy: "0.25rem", + dy: defaultLabelDy, fontSize: `${valueTickLabelSize / 16}rem`, height: categoryScale.bandwidth(), }; @@ -531,27 +513,6 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) { }} /> -
); }