mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-10 16:19:24 -07:00
feat(stats): unify chart theme and add gridlines for legibility
This commit is contained in:
@@ -1,7 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
|
||||
import {
|
||||
BarChart,
|
||||
Bar,
|
||||
CartesianGrid,
|
||||
XAxis,
|
||||
YAxis,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import { epochDayToDate } from '../../lib/formatters';
|
||||
import { CHART_THEME } from '../../lib/chart-theme';
|
||||
import { CHART_DEFAULTS, CHART_THEME, TOOLTIP_CONTENT_STYLE } from '../../lib/chart-theme';
|
||||
import type { DailyRollup } from '../../types/stats';
|
||||
|
||||
interface WatchTimeChartProps {
|
||||
@@ -52,28 +60,23 @@ export function WatchTimeChart({ rollups }: WatchTimeChartProps) {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<ResponsiveContainer width="100%" height={160}>
|
||||
<BarChart data={chartData}>
|
||||
<ResponsiveContainer width="100%" height={CHART_DEFAULTS.height}>
|
||||
<BarChart data={chartData} margin={CHART_DEFAULTS.margin}>
|
||||
<CartesianGrid stroke={CHART_THEME.grid} {...CHART_DEFAULTS.grid} />
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tick={{ fontSize: 10, fill: CHART_THEME.tick }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
tick={{ fontSize: 10, fill: CHART_THEME.tick }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
width={30}
|
||||
width={32}
|
||||
/>
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
background: CHART_THEME.tooltipBg,
|
||||
border: `1px solid ${CHART_THEME.tooltipBorder}`,
|
||||
borderRadius: 6,
|
||||
color: CHART_THEME.tooltipText,
|
||||
fontSize: 12,
|
||||
}}
|
||||
contentStyle={TOOLTIP_CONTENT_STYLE}
|
||||
labelStyle={{ color: CHART_THEME.tooltipLabel }}
|
||||
formatter={formatActiveMinutes}
|
||||
/>
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
|
||||
import {
|
||||
AreaChart,
|
||||
Area,
|
||||
CartesianGrid,
|
||||
XAxis,
|
||||
YAxis,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import { CHART_DEFAULTS, CHART_THEME, TOOLTIP_CONTENT_STYLE } from '../../lib/chart-theme';
|
||||
import { epochDayToDate } from '../../lib/formatters';
|
||||
|
||||
export interface PerAnimeDataPoint {
|
||||
@@ -64,14 +73,6 @@ export function StackedTrendChart({ title, data, colorPalette }: StackedTrendCha
|
||||
const { points, seriesKeys } = buildLineData(data);
|
||||
const colors = colorPalette ?? DEFAULT_LINE_COLORS;
|
||||
|
||||
const tooltipStyle = {
|
||||
background: '#363a4f',
|
||||
border: '1px solid #494d64',
|
||||
borderRadius: 6,
|
||||
color: '#cad3f5',
|
||||
fontSize: 12,
|
||||
};
|
||||
|
||||
if (points.length === 0) {
|
||||
return (
|
||||
<div className="bg-ctp-surface0 border border-ctp-surface1 rounded-lg p-4">
|
||||
@@ -84,21 +85,22 @@ export function StackedTrendChart({ title, data, colorPalette }: StackedTrendCha
|
||||
return (
|
||||
<div className="bg-ctp-surface0 border border-ctp-surface1 rounded-lg p-4">
|
||||
<h3 className="text-xs font-semibold text-ctp-text mb-2">{title}</h3>
|
||||
<ResponsiveContainer width="100%" height={120}>
|
||||
<AreaChart data={points}>
|
||||
<ResponsiveContainer width="100%" height={CHART_DEFAULTS.height}>
|
||||
<AreaChart data={points} margin={CHART_DEFAULTS.margin}>
|
||||
<CartesianGrid stroke={CHART_THEME.grid} {...CHART_DEFAULTS.grid} />
|
||||
<XAxis
|
||||
dataKey="label"
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
width={28}
|
||||
width={32}
|
||||
/>
|
||||
<Tooltip contentStyle={tooltipStyle} />
|
||||
<Tooltip contentStyle={TOOLTIP_CONTENT_STYLE} />
|
||||
{seriesKeys.map((key, i) => (
|
||||
<Area
|
||||
key={key}
|
||||
|
||||
@@ -6,8 +6,10 @@ import {
|
||||
XAxis,
|
||||
YAxis,
|
||||
Tooltip,
|
||||
CartesianGrid,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import { CHART_DEFAULTS, CHART_THEME, TOOLTIP_CONTENT_STYLE } from '../../lib/chart-theme';
|
||||
|
||||
interface TrendChartProps {
|
||||
title: string;
|
||||
@@ -19,35 +21,29 @@ interface TrendChartProps {
|
||||
}
|
||||
|
||||
export function TrendChart({ title, data, color, type, formatter, onBarClick }: TrendChartProps) {
|
||||
const tooltipStyle = {
|
||||
background: '#363a4f',
|
||||
border: '1px solid #494d64',
|
||||
borderRadius: 6,
|
||||
color: '#cad3f5',
|
||||
fontSize: 12,
|
||||
};
|
||||
|
||||
const formatValue = (v: number) => (formatter ? [formatter(v), title] : [String(v), title]);
|
||||
|
||||
return (
|
||||
<div className="bg-ctp-surface0 border border-ctp-surface1 rounded-lg p-4">
|
||||
<h3 className="text-xs font-semibold text-ctp-text mb-2">{title}</h3>
|
||||
<ResponsiveContainer width="100%" height={120}>
|
||||
<ResponsiveContainer width="100%" height={CHART_DEFAULTS.height}>
|
||||
{type === 'bar' ? (
|
||||
<BarChart data={data}>
|
||||
<BarChart data={data} margin={CHART_DEFAULTS.margin}>
|
||||
<CartesianGrid stroke={CHART_THEME.grid} {...CHART_DEFAULTS.grid} />
|
||||
<XAxis
|
||||
dataKey="label"
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
width={28}
|
||||
width={32}
|
||||
tickFormatter={formatter}
|
||||
/>
|
||||
<Tooltip contentStyle={tooltipStyle} formatter={formatValue} />
|
||||
<Tooltip contentStyle={TOOLTIP_CONTENT_STYLE} formatter={formatValue} />
|
||||
<Bar
|
||||
dataKey="value"
|
||||
fill={color}
|
||||
@@ -59,20 +55,22 @@ export function TrendChart({ title, data, color, type, formatter, onBarClick }:
|
||||
/>
|
||||
</BarChart>
|
||||
) : (
|
||||
<LineChart data={data}>
|
||||
<LineChart data={data} margin={CHART_DEFAULTS.margin}>
|
||||
<CartesianGrid stroke={CHART_THEME.grid} {...CHART_DEFAULTS.grid} />
|
||||
<XAxis
|
||||
dataKey="label"
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
tick={{ fontSize: 9, fill: '#a5adcb' }}
|
||||
axisLine={false}
|
||||
tick={{ fontSize: CHART_DEFAULTS.tickFontSize, fill: CHART_THEME.tick }}
|
||||
axisLine={{ stroke: CHART_THEME.axisLine }}
|
||||
tickLine={false}
|
||||
width={28}
|
||||
width={32}
|
||||
tickFormatter={formatter}
|
||||
/>
|
||||
<Tooltip contentStyle={tooltipStyle} formatter={formatValue} />
|
||||
<Tooltip contentStyle={TOOLTIP_CONTENT_STYLE} formatter={formatValue} />
|
||||
<Line dataKey="value" stroke={color} strokeWidth={2} dot={false} />
|
||||
</LineChart>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user