detached ef844de

refactor(ui): use CSS variables for chart colors instead of hardcoded values

Update DailyVisitsChart and HourlyActivityChart to consume injected theme
CSS variables (--primary, --muted-foreground, --border) instead of hardcoded
color values. Adds getAccentColor() helper to safely read --primary from
root element with fallback support.
commit
ef844de6ca7567f04093e66c4418f0969a3ff3d2
author
brice · · 2025-12-18 17:04 UTC
parent
ccc1c3e
signature
unsigned
2 files · +18 -8
M webui/src/pages/homepage/analytics/DailyVisitsChart.svelte +9 -4
@@ -12,6 +12,11 @@
1212 let container: HTMLDivElement;
1313 let chart: Chart | null = null;
1414
15+ // Get accent color from CSS variable
16+ function getAccentColor(): string {
17+ return getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#4ade80';
18+ }
19+
1520 // Convert data to Frappe Charts format
1621 const chartData = $derived.by(() => {
1722 if (!dailyVisits || dailyVisits.length === 0) {
@@ -40,7 +45,7 @@
4045 data: chartData,
4146 type: 'line',
4247 height: 160,
43- colors: ['#4ade80'],
48+ colors: [getAccentColor()],
4449 axisOptions: { xAxisMode: 'tick', xIsSeries: true },
4550 lineOptions: { regionFill: 1, hideDots: 0, dotSize: 4 },
4651 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }
@@ -90,7 +95,7 @@
9095 }
9196
9297 .chart-label {
93- color: #4ade80;
98+ color: var(--primary, #4ade80);
9499 font-weight: 600;
95100 }
96101
@@ -108,12 +113,12 @@
108113
109114 .chart-container :global(.frappe-chart .axis text),
110115 .chart-container :global(.frappe-chart .chart-label) {
111- fill: #737373;
116+ fill: var(--muted-foreground, #737373);
112117 font-size: 10px;
113118 }
114119
115120 .chart-container :global(.frappe-chart .axis line),
116121 .chart-container :global(.frappe-chart .chart-strokes) {
117- stroke: #333;
122+ stroke: var(--border, #333);
118123 }
119124 </style>
@@ -12,6 +12,11 @@
12 let container: HTMLDivElement;12 let container: HTMLDivElement;
13 let chart: Chart | null = null;13 let chart: Chart | null = null;
14 14
15+ // Get accent color from CSS variable
16+ function getAccentColor(): string {
17+ return getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#4ade80';
18+ }
19+
15 // Convert data to Frappe Charts format20 // Convert data to Frappe Charts format
16 const chartData = $derived.by(() => {21 const chartData = $derived.by(() => {
17 if (!dailyVisits || dailyVisits.length === 0) {22 if (!dailyVisits || dailyVisits.length === 0) {
@@ -40,7 +45,7 @@
40 data: chartData,45 data: chartData,
41 type: 'line',46 type: 'line',
42 height: 160,47 height: 160,
43- colors: ['#4ade80'],48+ colors: [getAccentColor()],
44 axisOptions: { xAxisMode: 'tick', xIsSeries: true },49 axisOptions: { xAxisMode: 'tick', xIsSeries: true },
45 lineOptions: { regionFill: 1, hideDots: 0, dotSize: 4 },50 lineOptions: { regionFill: 1, hideDots: 0, dotSize: 4 },
46 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }51 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }
@@ -90,7 +95,7 @@
90 }95 }
91 96
92 .chart-label {97 .chart-label {
93- color: #4ade80;98+ color: var(--primary, #4ade80);
94 font-weight: 600;99 font-weight: 600;
95 }100 }
96 101
@@ -108,12 +113,12 @@
108 113
109 .chart-container :global(.frappe-chart .axis text),114 .chart-container :global(.frappe-chart .axis text),
110 .chart-container :global(.frappe-chart .chart-label) {115 .chart-container :global(.frappe-chart .chart-label) {
111- fill: #737373;116+ fill: var(--muted-foreground, #737373);
112 font-size: 10px;117 font-size: 10px;
113 }118 }
114 119
115 .chart-container :global(.frappe-chart .axis line),120 .chart-container :global(.frappe-chart .axis line),
116 .chart-container :global(.frappe-chart .chart-strokes) {121 .chart-container :global(.frappe-chart .chart-strokes) {
117- stroke: #333;122+ stroke: var(--border, #333);
118 }123 }
119 </style>124 </style>
M webui/src/pages/homepage/analytics/HourlyActivityChart.svelte +9 -4
@@ -12,6 +12,11 @@
1212 let container: HTMLDivElement;
1313 let chart: Chart | null = null;
1414
15+ // Get accent color from CSS variable
16+ function getAccentColor(): string {
17+ return getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#4ade80';
18+ }
19+
1520 // Convert data to Frappe Charts format (ensure all 24 hours)
1621 const chartData = $derived.by(() => {
1722 const visitsByHour = new Map<number, number>();
@@ -47,7 +52,7 @@
4752 data: chartData,
4853 type: 'bar',
4954 height: 120,
50- colors: ['#4ade80'],
55+ colors: [getAccentColor()],
5156 axisOptions: { xAxisMode: 'tick' },
5257 barOptions: { spaceRatio: 0.3 },
5358 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }
@@ -95,7 +100,7 @@
95100 }
96101
97102 .chart-label {
98- color: #4ade80;
103+ color: var(--primary, #4ade80);
99104 font-weight: 600;
100105 }
101106
@@ -113,12 +118,12 @@
113118
114119 .chart-container :global(.frappe-chart .axis text),
115120 .chart-container :global(.frappe-chart .chart-label) {
116- fill: #737373;
121+ fill: var(--muted-foreground, #737373);
117122 font-size: 10px;
118123 }
119124
120125 .chart-container :global(.frappe-chart .axis line),
121126 .chart-container :global(.frappe-chart .chart-strokes) {
122- stroke: #333;
127+ stroke: var(--border, #333);
123128 }
124129 </style>
@@ -12,6 +12,11 @@
12 let container: HTMLDivElement;12 let container: HTMLDivElement;
13 let chart: Chart | null = null;13 let chart: Chart | null = null;
14 14
15+ // Get accent color from CSS variable
16+ function getAccentColor(): string {
17+ return getComputedStyle(document.documentElement).getPropertyValue('--primary').trim() || '#4ade80';
18+ }
19+
15 // Convert data to Frappe Charts format (ensure all 24 hours)20 // Convert data to Frappe Charts format (ensure all 24 hours)
16 const chartData = $derived.by(() => {21 const chartData = $derived.by(() => {
17 const visitsByHour = new Map<number, number>();22 const visitsByHour = new Map<number, number>();
@@ -47,7 +52,7 @@
47 data: chartData,52 data: chartData,
48 type: 'bar',53 type: 'bar',
49 height: 120,54 height: 120,
50- colors: ['#4ade80'],55+ colors: [getAccentColor()],
51 axisOptions: { xAxisMode: 'tick' },56 axisOptions: { xAxisMode: 'tick' },
52 barOptions: { spaceRatio: 0.3 },57 barOptions: { spaceRatio: 0.3 },
53 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }58 tooltipOptions: { formatTooltipY: (d: number) => `${d} visits` }
@@ -95,7 +100,7 @@
95 }100 }
96 101
97 .chart-label {102 .chart-label {
98- color: #4ade80;103+ color: var(--primary, #4ade80);
99 font-weight: 600;104 font-weight: 600;
100 }105 }
101 106
@@ -113,12 +118,12 @@
113 118
114 .chart-container :global(.frappe-chart .axis text),119 .chart-container :global(.frappe-chart .axis text),
115 .chart-container :global(.frappe-chart .chart-label) {120 .chart-container :global(.frappe-chart .chart-label) {
116- fill: #737373;121+ fill: var(--muted-foreground, #737373);
117 font-size: 10px;122 font-size: 10px;
118 }123 }
119 124
120 .chart-container :global(.frappe-chart .axis line),125 .chart-container :global(.frappe-chart .axis line),
121 .chart-container :global(.frappe-chart .chart-strokes) {126 .chart-container :global(.frappe-chart .chart-strokes) {
122- stroke: #333;127+ stroke: var(--border, #333);
123 }128 }
124 </style>129 </style>

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close