fix visual nits + tooltip

This commit is contained in:
e26chiu 2022-09-03 10:36:03 -04:00
parent e346069421
commit d53468a0eb
3 changed files with 187 additions and 216 deletions

View File

@ -9,7 +9,7 @@
.legend { .legend {
position: absolute; position: absolute;
display: flex; display: flex;
font-size: 16px; font-size: calc(16rem / 16);
top: 0; top: 0;
} }
@ -27,7 +27,7 @@
} }
.toolTip p { .toolTip p {
margin: 0 5px; margin: 0 calc(5rem / 16);
font-size: calc(16rem / 16); font-size: calc(16rem / 16);
} }

View File

@ -7,7 +7,9 @@ import { Point } from "@visx/point";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale"; import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { BarStack, Line } from "@visx/shape"; import { BarStack, Line } from "@visx/shape";
import { SeriesPoint } from "@visx/shape/lib/types"; import { SeriesPoint } from "@visx/shape/lib/types";
import { useTooltip, useTooltipInPortal, defaultStyles } from "@visx/tooltip"; //import { useTooltip, useTooltipInPortal, withTooltip } from "@visx/tooltip";
import { withTooltip, Tooltip } from "@visx/tooltip";
import { WithTooltipProvidedProps } from "@visx/tooltip/lib/enhancers/withTooltip";
import React from "react"; import React from "react";
import { Color } from "utils/Color"; import { Color } from "utils/Color";
@ -45,6 +47,8 @@ export type StackedBarProps = {
numTicksLeftAxis?: number; numTicksLeftAxis?: number;
/** Distance between the left axis labels and the start of the lines of the graph, in px. */ /** Distance between the left axis labels and the start of the lines of the graph, in px. */
valueAxisLeftOffset?: number; valueAxisLeftOffset?: number;
/** Distance between the bottom axis and the bottom of the container of the graph, in px. */
categoryAxisBottomOffset?: number;
/** Distance between the right side of the graph and the legend, in px. */ /** Distance between the right side of the graph and the legend, in px. */
legendLeftOffset?: number; legendLeftOffset?: number;
/** Distance between the top of the graph and the legend, in px. */ /** Distance between the top of the graph and the legend, in px. */
@ -57,11 +61,14 @@ export type StackedBarProps = {
scalePadding?: number; scalePadding?: number;
/** Margin for each item in the legend */ /** Margin for each item in the legend */
itemMargin?: string; itemMargin?: string;
/** Factor multiplied to the left offset to center the labels in the x-axis. >1 for width <600 and <1 for width >600 */
categoryAxisLeftFactor?: number;
}; };
let tooltipTimeout: number; let tooltipTimeout: number;
export function StackedBarGraph({ export const StackedBarGraph = withTooltip<StackedBarProps, TooltipData>(
({
data, data,
width, width,
height, height,
@ -71,12 +78,20 @@ export function StackedBarGraph({
scalePadding = 0.3, scalePadding = 0.3,
numTicksLeftAxis = 6, numTicksLeftAxis = 6,
valueAxisLeftOffset = 40, valueAxisLeftOffset = 40,
categoryAxisBottomOffset = 40,
strokeWidth = 2.5, strokeWidth = 2.5,
strokeDashArray = "10,4", strokeDashArray = "10,4",
legendLeftOffset = 40, legendLeftOffset = 40,
legendTopOffset = 40, legendTopOffset = 40,
itemMargin = "15px 0 0 0", itemMargin = "15px 0 0 0",
}: StackedBarProps) { categoryAxisLeftFactor = 1,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
}: StackedBarProps & WithTooltipProvidedProps<TooltipData>) => {
const yTotals = data.reduce((allTotals, currCategory) => { const yTotals = data.reduce((allTotals, currCategory) => {
const yTotal = keys.reduce((categoryTotal, k) => { const yTotal = keys.reduce((categoryTotal, k) => {
categoryTotal += currCategory[k] as number; categoryTotal += currCategory[k] as number;
@ -104,32 +119,17 @@ export function StackedBarGraph({
domain: keys, domain: keys,
range: colorRange, range: colorRange,
}); });
const {
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
} = useTooltip<TooltipData>();
const { containerRef, TooltipInPortal } = useTooltipInPortal({
// TooltipInPortal is rendered in a separate child of <body /> and positioned
// with page coordinates which should be updated on scroll.
scroll: true,
});
if (width < 10) return null;
// bounds // bounds
const xMax = width; const xMax = width;
const yMax = height - margin.top - 50; const yMax = height - margin.top - categoryAxisBottomOffset;
xScale.rangeRound([0, xMax - valueAxisLeftOffset]); xScale.rangeRound([0, xMax - valueAxisLeftOffset]);
yScale.range([yMax, 0]); yScale.range([yMax, 0]);
return width < 10 ? null : ( return width < 10 ? null : (
<div className={styles.container}> <div className={styles.container}>
<svg ref={containerRef} width={width} height={height}> <svg width={width} height={height}>
<Group top={margin.top} left={margin.left}> <Group top={margin.top} left={margin.left}>
<GridRows <GridRows
scale={yScale} scale={yScale}
@ -144,7 +144,7 @@ export function StackedBarGraph({
<GridColumns <GridColumns
scale={xScale} scale={xScale}
height={yMax} height={yMax}
left={xScale.bandwidth() / 2} left={valueAxisLeftOffset}
offset={xScale.bandwidth() / 2} offset={xScale.bandwidth() / 2}
stroke={Color.tertiaryBackground} stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth} strokeWidth={strokeWidth}
@ -177,8 +177,6 @@ export function StackedBarGraph({
}} }}
onMouseMove={(event) => { onMouseMove={(event) => {
if (tooltipTimeout) clearTimeout(tooltipTimeout); if (tooltipTimeout) clearTimeout(tooltipTimeout);
// TooltipInPortal expects coordinates to be relative to containerRef
// localPoint returns coordinates relative to the nearest SVG
const eventSvgCoords = localPoint(event); const eventSvgCoords = localPoint(event);
const left = bar.x + bar.width / 2; const left = bar.x + bar.width / 2;
showTooltip({ showTooltip({
@ -204,7 +202,9 @@ export function StackedBarGraph({
<AxisBottom <AxisBottom
top={yMax} top={yMax}
scale={xScale} scale={xScale}
left={xScale.bandwidth() / 6} left={
((xScale.bandwidth() * 100) / width) * categoryAxisLeftFactor
}
hideTicks hideTicks
hideAxisLine hideAxisLine
labelProps={{ labelProps={{
@ -244,7 +244,7 @@ export function StackedBarGraph({
</div> </div>
{tooltipOpen && tooltipData ? ( {tooltipOpen && tooltipData ? (
<TooltipInPortal <Tooltip
className={styles.toolTip} className={styles.toolTip}
top={tooltipTop} top={tooltipTop}
left={tooltipLeft} left={tooltipLeft}
@ -253,8 +253,9 @@ export function StackedBarGraph({
<p className={styles.key}>{tooltipData.key}</p> <p className={styles.key}>{tooltipData.key}</p>
<p>{tooltipData.bar.data[tooltipData.key]}</p> <p>{tooltipData.bar.data[tooltipData.key]}</p>
<p>{getCategory(tooltipData.bar.data)}</p> <p>{getCategory(tooltipData.bar.data)}</p>
</TooltipInPortal> </Tooltip>
) : null} ) : null}
</div> </div>
); );
} }
);

View File

@ -65,36 +65,6 @@ export const moreMockCategoricalData = [
{ key: "Dart", value: 2.21 }, { key: "Dart", value: 2.21 },
]; ];
export const mockBoxPlotData = [
{
x: "1A",
min: 20,
firstQuartile: 25,
median: 30,
thirdQuartile: 80,
max: 100,
outliers: [],
},
{
x: "1B",
min: 0,
firstQuartile: 20,
median: 30,
thirdQuartile: 50,
max: 100,
outliers: [],
},
{
x: "2A",
min: 25,
firstQuartile: 35,
median: 50,
thirdQuartile: 90,
max: 100,
outliers: [],
},
];
export const mockStackedBarGraphData = [ export const mockStackedBarGraphData = [
{ {
category: "1A", category: "1A",