Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
6 changes: 6 additions & 0 deletions web/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ declare module "styled-components" {
//eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DefaultTheme extends Theme {}
}

declare module "chart.js" {
interface TooltipPositionerMap {
custom: TooltipPositionerFunction<ChartType>;
}
}
20 changes: 20 additions & 0 deletions web/src/pages/Home/CourtOverview/Chart.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useMemo, useState } from "react";
import styled from "styled-components";

import { Tooltip } from "chart.js";
import { formatUnits } from "viem";

import { DropdownSelect } from "@kleros/ui-components-library";
Expand Down Expand Up @@ -101,4 +102,23 @@ const Chart: React.FC = () => {
);
};

// custom positioner for tooltip, we need dynamic top positioning, which is not available by default.
Tooltip.positioners.custom = function (elements) {
const tooltip = this;
const height = tooltip.chart.chartArea.height;
const width = tooltip.chart.chartArea.width;

const x = elements[0]?.element.x;
const y = elements[0]?.element.y;
const isAtTop = height > y + tooltip.height;
const isAtEnd = width < x + tooltip.width;

return {
x: elements[0]?.element.x,
y: elements[0]?.element.y,
xAlign: isAtTop ? (isAtEnd ? "right" : "left") : "center",
yAlign: isAtTop ? "center" : "bottom",
};
};

export default Chart;
45 changes: 42 additions & 3 deletions web/src/pages/Home/CourtOverview/TimeSeriesChart.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import React from "react";
import styled, { useTheme } from "styled-components";

import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, TimeScale, Tooltip } from "chart.js";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
TimeScale,
Tooltip,
ScriptableContext,
} from "chart.js";
import { Line } from "react-chartjs-2";
import "chartjs-adapter-moment";

Expand Down Expand Up @@ -51,6 +60,7 @@ const TimeSeriesChart: React.FC<ITimeSeriesChart> = ({ data }) => {
},
plugins: {
tooltip: {
position: "custom",
backgroundColor: theme.whiteBackground,
titleColor: theme.primaryText,
borderColor: theme.stroke,
Expand All @@ -74,18 +84,47 @@ const TimeSeriesChart: React.FC<ITimeSeriesChart> = ({ data }) => {
datasets: [
{
data,
borderColor: theme.primaryBlue,
// borderColor: theme.primaryBlue,
stepped: true,
cubicInterpolationMode: "monotone",
borderColor: (context: ScriptableContext<"line">) => {
const ctx = context.chart.ctx;
const gradient = ctx.createLinearGradient(0, 0, 0, 200);
gradient.addColorStop(0, theme.primaryBlue);
gradient.addColorStop(1, theme.secondaryPurple);
return gradient;
},
},
],
},
options,
}}
plugins={[
{
id: "line-draw",
afterDatasetsDraw: (chart) => {
if (chart.tooltip?._active?.length) {
const x = chart.tooltip._active[0].element.x;
const y = chart.tooltip._active[0].element.y;
const yAxis = chart.scales.y;

const ctx = chart.ctx;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, yAxis.bottom);
ctx.lineWidth = 1;
ctx.strokeStyle = theme.secondaryPurple;
ctx.setLineDash([4, 4]);
ctx.stroke();
ctx.restore();
}
},
},
]}
/>
}
</LineContainer>
);
};

export default TimeSeriesChart;