+
{truncateText(campaign.name, 18)}
diff --git a/frontend/src/lib/components/CampaignTrendChart.svelte b/frontend/src/lib/components/CampaignTrendChart.svelte
index 78a71f5..363b422 100644
--- a/frontend/src/lib/components/CampaignTrendChart.svelte
+++ b/frontend/src/lib/components/CampaignTrendChart.svelte
@@ -2,6 +2,21 @@
import { onMount, onDestroy, tick } from 'svelte';
let resizeObserver;
+ // Theme detection for chart reactivity
+ let isDarkMode = false;
+
+ // Check theme on mount and when it changes
+ const checkTheme = () => {
+ const newIsDarkMode = document.documentElement.classList.contains('dark');
+ if (newIsDarkMode !== isDarkMode) {
+ isDarkMode = newIsDarkMode;
+ // Recreate chart when theme changes
+ if (containerReady && chartData.length >= 2) {
+ tick().then(() => createChart());
+ }
+ }
+ };
+
export let campaignStats = [];
export let isLoading = false;
@@ -238,6 +253,16 @@
svg.setAttribute('class', 'campaign-trend-chart');
chartContainer.appendChild(svg);
+ // Add dark background rectangle
+ const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+ bgRect.setAttribute('width', '100%');
+ bgRect.setAttribute('height', '100%');
+ bgRect.setAttribute(
+ 'fill',
+ document.documentElement.classList.contains('dark') ? '#111827' : '#ffffff'
+ );
+ svg.appendChild(bgRect);
+
const xExtent = [0, chartData.length - 1];
// Map 0-100% directly to chart boundaries so 0% aligns with X-axis
const yExtent = [0, 100];
@@ -346,7 +371,7 @@
stop1.setAttribute('offset', '0%');
stop1.setAttribute(
'stop-color',
- document.documentElement.classList.contains('dark') ? '#374151' : '#f8f9fa'
+ document.documentElement.classList.contains('dark') ? '#1f2937' : '#f8f9fa'
);
stop1.setAttribute('stop-opacity', '0.3');
@@ -354,15 +379,15 @@
stop2.setAttribute('offset', '50%');
stop2.setAttribute(
'stop-color',
- document.documentElement.classList.contains('dark') ? '#4b5563' : '#e9ecef'
+ document.documentElement.classList.contains('dark') ? '#374151' : '#e9ecef'
);
- stop2.setAttribute('stop-opacity', '0.5');
+ stop2.setAttribute('stop-opacity', '0.4');
const stop3 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
stop3.setAttribute('offset', '100%');
stop3.setAttribute(
'stop-color',
- document.documentElement.classList.contains('dark') ? '#374151' : '#f8f9fa'
+ document.documentElement.classList.contains('dark') ? '#1f2937' : '#f8f9fa'
);
stop3.setAttribute('stop-opacity', '0.3');
@@ -400,7 +425,7 @@
vLine.setAttribute('y2', (height - margin.bottom).toString());
vLine.setAttribute(
'stroke',
- document.documentElement.classList.contains('dark') ? '#4b5563' : '#e5e7eb'
+ document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'
);
vLine.setAttribute('stroke-width', '0.5');
vLine.setAttribute('opacity', '0.3');
@@ -416,7 +441,7 @@
yAxis.setAttribute('y2', (height - margin.bottom).toString());
yAxis.setAttribute(
'stroke',
- document.documentElement.classList.contains('dark') ? '#9ca3af' : '#6B7280'
+ document.documentElement.classList.contains('dark') ? '#6887ea' : '#6B7280'
);
yAxis.setAttribute('stroke-width', '2');
svg.appendChild(yAxis);
@@ -428,7 +453,7 @@
xAxis.setAttribute('y2', (height - margin.bottom).toString());
xAxis.setAttribute(
'stroke',
- document.documentElement.classList.contains('dark') ? '#9ca3af' : '#6B7280'
+ document.documentElement.classList.contains('dark') ? '#6887ea' : '#6B7280'
);
xAxis.setAttribute('stroke-width', '2');
svg.appendChild(xAxis);
@@ -443,7 +468,7 @@
text.setAttribute('font-size', '11');
text.setAttribute(
'fill',
- document.documentElement.classList.contains('dark') ? '#d1d5db' : '#6B7280'
+ document.documentElement.classList.contains('dark') ? '#e5e7eb' : '#6B7280'
);
text.setAttribute('font-weight', '500');
text.setAttribute('alignment-baseline', 'middle');
@@ -461,7 +486,7 @@
text.setAttribute('font-size', '11');
text.setAttribute(
'fill',
- document.documentElement.classList.contains('dark') ? '#f9fafb' : '#000'
+ document.documentElement.classList.contains('dark') ? '#f3f4f6' : '#000'
);
text.setAttribute('alignment-baseline', 'middle');
// Show date (YYYY/MM) and campaign name on the same line
@@ -810,8 +835,21 @@
});
}
+ let themeObserver;
+
onMount(async () => {
await tick(); // Wait for DOM/layout
+
+ // Initialize theme detection
+ checkTheme();
+
+ // Watch for theme changes
+ themeObserver = new MutationObserver(checkTheme);
+ themeObserver.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['class']
+ });
+
if (sizingContainer) {
const containerWidth = sizingContainer.parentElement?.clientWidth || 0;
width = Math.min(Math.max(containerWidth, 300), containerWidth); // Minimum 300px but never exceed container
@@ -833,6 +871,10 @@
if (resizeObserver && sizingContainer) {
resizeObserver.unobserve(sizingContainer.parentElement || sizingContainer);
}
+ // Clean up theme observer
+ if (themeObserver) {
+ themeObserver.disconnect();
+ }
if (loadingTimeout) {
clearTimeout(loadingTimeout);
}
@@ -856,14 +898,16 @@
>
{#if !containerReady}