WIP: Line Graph Component #21

Closed
b72zhou wants to merge 14 commits from b72zhou-line-graph into main
3 changed files with 111 additions and 60 deletions
Showing only changes of commit 991006ddb6 - Show all commits

View File

@ -33,4 +33,4 @@
font-family: "Inconsolata", monospace;
font-weight: 800;
fill: var(--label);
}
}

View File

@ -5,13 +5,12 @@
fill: var(--label);
}
.lineGroup:hover .line {
fill: var(--primary-accent);
filter: drop-shadow(0 0 calc(4rem / 16) var(--primary-accent));
.lineSeries {
/* fill: var(--label); */
}
.lineGroup:hover .lineText {
visibility: visible;
.lineSeries:hover {
filter: drop-shadow(0 0 calc(4rem / 16) var(--primary-accent));
}
.axisLabel {

View File

@ -1,13 +1,15 @@
import { localPoint } from "@visx/event";
import {
useTooltip,
useTooltipInPortal,
TooltipWithBounds,
} from "@visx/tooltip";
import {
Axis,
Grid,
buildChartTheme,
LineSeries,
XYChart,
Annotation,
AnnotationLabel,
AnnotationConnector,
AnnotationCircleSubject,
} from "@visx/xychart";
import React from "react";
import { Color } from "utils/Color";
@ -19,7 +21,7 @@ interface LineGraphData {
y: number;
}
interface BarGraphProps {
interface LineGraphProps {
data: LineGraphData[][];
width: number;
height: number;
@ -33,7 +35,12 @@ interface BarGraphProps {
yLabelSize?: number;
Review

This probably shouldn't be hard coded in the final component 😛

This probably shouldn't be hard coded in the final component 😛
}
interface TooltipData {
name?: string;
}
const DEFAULT_LABEL_SIZE = 16;
let tooltipTimeout: number;
export function LineGraph({
Review

Is it possible to cast this to a type (maybe visx has a type we can import?) to get rid of the unsafe assignment complaints?

Is it possible to cast this to a type (maybe visx has a type we can import?) to get rid of the unsafe assignment complaints?
data,
@ -42,8 +49,31 @@ export function LineGraph({
margin,
xLabelSize = DEFAULT_LABEL_SIZE,
yLabelSize = DEFAULT_LABEL_SIZE,
}: BarGraphProps) {
if (width < 10) return null;
}: LineGraphProps) {
const {
tooltipData,
tooltipLeft,
tooltipTop,
tooltipOpen,
showTooltip,
hideTooltip,
} = useTooltip();
const { containerRef, TooltipInPortal } = useTooltipInPortal({
// use TooltipWithBounds
detectBounds: true,
// when tooltip containers are scrolled, this will correctly update the Tooltip position
scroll: true,
});
const handleMouseOver = (event: React.MouseEvent<SVGRectElement>, datum) => {
const coords = localPoint(event);
showTooltip({
tooltipLeft: coords.x,
tooltipTop: coords.y,
tooltipData: datum,
});
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const customTheme = buildChartTheme({
@ -63,59 +93,81 @@ export function LineGraph({
const yAccessor = (d: LineGraphData) => d.y;
return (
<XYChart
height={height}
width={width}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
theme={customTheme}
margin={margin}
xScale={{ type: "band" }}
yScale={{ type: "linear" }}
>
<>
<rect
x={0}
y={0}
ref={containerRef}
width={width}
height={height}
fill={Color.primaryBackground}
/>
>
<XYChart
height={height}
width={width}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
theme={customTheme}
margin={margin}
xScale={{ type: "band" }}
yScale={{ type: "linear" }}
>
<Axis
orientation="bottom"
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
dy: "0.25rem",
fontSize: `${xLabelSize / 16}rem`,
className: styles.axisLabel,
};
}}
/>
<Axis
orientation="left"
hideAxisLine
hideTicks
numTicks={4}
rangePadding={100}
tickLabelProps={() => {
return {
dy: "0.25rem",
className: styles.axisLabel,
fontSize: `${yLabelSize / 16}rem`,
};
}}
/>
<Grid
numTicks={data[0].length}
strokeWidth={50}
strokeDasharray="10"
/>
{data.map((d, i) => (
<LineSeries
enableEvents
className={styles.lineSeries} // Why doesn't work???
dataKey={i.toString()}
key={i}
data={d}
xAccessor={xAccessor}
yAccessor={yAccessor}
// onFocus={handleMouseOver}
// onMouseOut={hideTooltip}
/>
))}
</XYChart>
</rect>
{data.map((d, i) => (
<LineSeries
dataKey={i.toString()}
key={i}
data={d}
xAccessor={xAccessor}
yAccessor={yAccessor}
/>
))}
<Axis
orientation="bottom"
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
dy: "0.25rem",
fontSize: `${xLabelSize / 16}rem`,
className: styles.axisLabel,
};
}}
/>
<Axis
orientation="left"
hideAxisLine
hideTicks
numTicks={4}
rangePadding={100}
tickLabelProps={() => {
return {
dy: "0.25rem",
className: styles.axisLabel,
fontSize: `${yLabelSize / 16}rem`,
};
}}
/>
<Grid numTicks={data[0].length} strokeWidth={0.5} strokeDasharray="6" />
</XYChart>
{tooltipOpen && (
<TooltipInPortal
// set this to random so it correctly updates with parent bounds
key={Math.random()}
top={tooltipTop}
left={tooltipLeft}
>
Data value <strong>{tooltipData}</strong>
</TooltipInPortal>
)}
</>
);
}