Merge pull request 'feat: theme-aware chart colors for dark/light mode' (#1348) from feature/1324-dark-mode-variants into main
Test and Lint / test (pull_request) Has been cancelled

This commit is contained in:
2026-03-30 15:03:43 +00:00
3 changed files with 63 additions and 37 deletions
+41
View File
@@ -0,0 +1,41 @@
import { useTheme } from './ThemeContext';
/**
* Returns theme-aware color values for recharts components.
*
* Recharts accepts only raw color strings (not CSS variables),
* so this hook bridges the Tailwind/CSS-variable theme system
* to the imperative recharts API.
*/
export function useChartTheme() {
const { theme } = useTheme();
const isDark = theme === 'dark';
return {
/** Axis tick and grid line stroke color */
axisStroke: isDark ? '#94a3b8' : '#64748b',
/** Tooltip container background */
tooltipBg: isDark ? '#1e293b' : '#ffffff',
/** Tooltip container border */
tooltipBorder: isDark
? '1px solid rgba(99, 102, 241, 0.3)'
: '1px solid rgba(99, 102, 241, 0.2)',
/** Tooltip label text color */
tooltipLabelColor: isDark ? '#f8fafc' : '#0f172a',
/** Tooltip item text color */
tooltipItemColor: isDark ? '#e2e8f0' : '#334155',
/** Convenience: full contentStyle object for recharts Tooltip */
tooltipContentStyle: {
backgroundColor: isDark ? '#1e293b' : '#ffffff',
border: isDark
? '1px solid rgba(99, 102, 241, 0.3)'
: '1px solid rgba(99, 102, 241, 0.2)',
borderRadius: '8px',
color: isDark ? '#f8fafc' : '#0f172a',
},
/** Convenience: labelStyle for recharts Tooltip */
tooltipLabelStyle: {
color: isDark ? '#f8fafc' : '#0f172a',
},
};
}
+15 -29
View File
@@ -3,11 +3,13 @@ import { useQuery } from '@tanstack/react-query';
import { analyticsApi } from '../api/client'; import { analyticsApi } from '../api/client';
import { AlertCircle, Database } from 'lucide-react'; import { AlertCircle, Database } from 'lucide-react';
import { PieChart, Pie, Cell, BarChart, Bar, LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts'; import { PieChart, Pie, Cell, BarChart, Bar, LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts';
import { useChartTheme } from '../context/useChartTheme';
const COLORS = ['#6366f1', '#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#14b8a6']; const COLORS = ['#6366f1', '#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#14b8a6'];
export function AnalyticsPage() { export function AnalyticsPage() {
const [days, setDays] = useState(30); const [days, setDays] = useState(30);
const chartTheme = useChartTheme();
const { data, isLoading, isError, refetch } = useQuery({ const { data, isLoading, isError, refetch } = useQuery({
queryKey: ['analytics', days], queryKey: ['analytics', days],
@@ -160,11 +162,7 @@ export function AnalyticsPage() {
))} ))}
</Pie> </Pie>
<Tooltip <Tooltip
contentStyle={{ contentStyle={chartTheme.tooltipContentStyle}
backgroundColor: '#1e293b',
border: '1px solid rgba(99, 102, 241, 0.3)',
borderRadius: '8px',
}}
/> />
<Legend /> <Legend />
</PieChart> </PieChart>
@@ -178,15 +176,11 @@ export function AnalyticsPage() {
<h3 className="text-lg font-semibold text-text-primary mb-4">Analysis Types</h3> <h3 className="text-lg font-semibold text-text-primary mb-4">Analysis Types</h3>
<ResponsiveContainer width="100%" height={300}> <ResponsiveContainer width="100%" height={300}>
<BarChart data={typeData}> <BarChart data={typeData}>
<XAxis dataKey="name" stroke="#94a3b8" fontSize={12} /> <XAxis dataKey="name" stroke={chartTheme.axisStroke} fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} /> <YAxis stroke={chartTheme.axisStroke} fontSize={12} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={chartTheme.tooltipContentStyle}
backgroundColor: '#1e293b', labelStyle={chartTheme.tooltipLabelStyle}
border: '1px solid rgba(99, 102, 241, 0.3)',
borderRadius: '8px',
}}
labelStyle={{ color: '#f8fafc' }}
/> />
<Bar dataKey="count" fill="#6366f1" radius={[4, 4, 0, 0]} /> <Bar dataKey="count" fill="#6366f1" radius={[4, 4, 0, 0]} />
</BarChart> </BarChart>
@@ -222,15 +216,11 @@ export function AnalyticsPage() {
<h4 className="text-md font-semibold text-text-primary mb-4">Analyses per Company Over Time</h4> <h4 className="text-md font-semibold text-text-primary mb-4">Analyses per Company Over Time</h4>
<ResponsiveContainer width="100%" height={300}> <ResponsiveContainer width="100%" height={300}>
<LineChart data={pivoted}> <LineChart data={pivoted}>
<XAxis dataKey="month" stroke="#94a3b8" fontSize={12} /> <XAxis dataKey="month" stroke={chartTheme.axisStroke} fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} /> <YAxis stroke={chartTheme.axisStroke} fontSize={12} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={chartTheme.tooltipContentStyle}
backgroundColor: '#1e293b', labelStyle={chartTheme.tooltipLabelStyle}
border: '1px solid rgba(99, 102, 241, 0.3)',
borderRadius: '8px',
}}
labelStyle={{ color: '#f8fafc' }}
/> />
<Legend /> <Legend />
{companies.map((company, idx) => ( {companies.map((company, idx) => (
@@ -268,15 +258,11 @@ export function AnalyticsPage() {
<h4 className="text-md font-semibold text-text-primary mb-4">Analysis Types Over Time</h4> <h4 className="text-md font-semibold text-text-primary mb-4">Analysis Types Over Time</h4>
<ResponsiveContainer width="100%" height={300}> <ResponsiveContainer width="100%" height={300}>
<BarChart data={pivoted}> <BarChart data={pivoted}>
<XAxis dataKey="month" stroke="#94a3b8" fontSize={12} /> <XAxis dataKey="month" stroke={chartTheme.axisStroke} fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} /> <YAxis stroke={chartTheme.axisStroke} fontSize={12} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={chartTheme.tooltipContentStyle}
backgroundColor: '#1e293b', labelStyle={chartTheme.tooltipLabelStyle}
border: '1px solid rgba(99, 102, 241, 0.3)',
borderRadius: '8px',
}}
labelStyle={{ color: '#f8fafc' }}
/> />
<Legend /> <Legend />
{types.map((type, idx) => ( {types.map((type, idx) => (
+7 -8
View File
@@ -3,6 +3,7 @@ import { useMutation, useQuery } from '@tanstack/react-query';
import { analysisApi } from '../api/client'; import { analysisApi } from '../api/client';
import { Rocket, CheckCircle, AlertCircle, ChevronDown, ChevronUp, RefreshCw, Inbox } from 'lucide-react'; import { Rocket, CheckCircle, AlertCircle, ChevronDown, ChevronUp, RefreshCw, Inbox } from 'lucide-react';
import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Cell } from 'recharts'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Cell } from 'recharts';
import { useChartTheme } from '../context/useChartTheme';
import type { BatchAnalysisResult } from '../types'; import type { BatchAnalysisResult } from '../types';
export function Batch() { export function Batch() {
@@ -12,6 +13,8 @@ export function Batch() {
const [result, setResult] = useState<BatchAnalysisResult | null>(null); const [result, setResult] = useState<BatchAnalysisResult | null>(null);
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set()); const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
const chartTheme = useChartTheme();
const modelsQuery = useQuery({ const modelsQuery = useQuery({
queryKey: ['models'], queryKey: ['models'],
queryFn: () => analysisApi.listModels(), queryFn: () => analysisApi.listModels(),
@@ -210,15 +213,11 @@ export function Batch() {
<div className="bg-bg-card/60 border border-primary/15 rounded-2xl p-6"> <div className="bg-bg-card/60 border border-primary/15 rounded-2xl p-6">
<ResponsiveContainer width="100%" height={300}> <ResponsiveContainer width="100%" height={300}>
<BarChart data={chartData}> <BarChart data={chartData}>
<XAxis dataKey="name" stroke="#94a3b8" fontSize={12} /> <XAxis dataKey="name" stroke={chartTheme.axisStroke} fontSize={12} />
<YAxis stroke="#94a3b8" fontSize={12} /> <YAxis stroke={chartTheme.axisStroke} fontSize={12} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={chartTheme.tooltipContentStyle}
backgroundColor: '#1e293b', labelStyle={chartTheme.tooltipLabelStyle}
border: '1px solid rgba(99, 102, 241, 0.3)',
borderRadius: '8px',
}}
labelStyle={{ color: '#f8fafc' }}
/> />
<Bar dataKey="patents" radius={[4, 4, 0, 0]}> <Bar dataKey="patents" radius={[4, 4, 0, 0]}>
{chartData.map((entry, index) => ( {chartData.map((entry, index) => (