Skip to content

Commit 9a9e70c

Browse files
committed
dark mode adjustments
1 parent 9b0c120 commit 9a9e70c

File tree

17 files changed

+899
-48
lines changed

17 files changed

+899
-48
lines changed

frontend/public/dark-theme.css

Lines changed: 547 additions & 0 deletions
Large diffs are not rendered by default.

frontend/public/index.html

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
<meta name="msapplication-TileColor" />
77
<meta name="theme-color" content="#ffffff"/>
88
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter"/>
9+
<link rel="stylesheet" href="theme-variables.css">
910
<link rel="stylesheet" type="text/css" href="style.css"/>
1011
<link rel="stylesheet" href="https://unpkg.com/prismjs@1.29.0/themes/prism.css"/>
1112
<link rel="stylesheet" href="tw.css">
13+
<link rel="stylesheet" href="dark-theme.css">
1214
<link rel="stylesheet" href="vanillatoasts/vanillatoasts.css">
1315
<link rel="stylesheet" href="https://unpkg.com/codemirror@5.65.16/lib/codemirror.css">
1416
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
@@ -20,26 +22,16 @@
2022
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
2123
<script src="https://unpkg.com/codemirror@5.65.16/lib/codemirror.js"></script>
2224
<script src="https://unpkg.com/codemirror@5.65.16/mode/javascript/javascript.js"></script>
23-
<!--Docs: https://www.npmjs.com/package/darkreader-->
24-
<script src="https://unpkg.com/darkreader@4.9.120"></script>
2525
<script>
2626
(function() {
27-
// to prevent a flash of light
2827
var key = 'studio-theme';
2928
var stored = localStorage.getItem(key);
3029
var prefersDark = typeof matchMedia !== 'undefined' && matchMedia('(prefers-color-scheme: dark)').matches;
3130
var isDark = stored === 'dark' || (!stored && prefersDark);
3231
if (!stored) localStorage.setItem(key, isDark ? 'dark' : 'light');
32+
if (isDark) document.documentElement.classList.add('dark');
3333
var meta = document.querySelector('meta[name="theme-color"]');
34-
if (typeof DarkReader !== 'undefined') {
35-
if (isDark) {
36-
DarkReader.enable({ brightness: 100, contrast: 95, sepia: 0 });
37-
if (meta) meta.setAttribute('content', '#1a1a1a');
38-
} else {
39-
DarkReader.disable();
40-
if (meta) meta.setAttribute('content', '#ffffff');
41-
}
42-
}
34+
if (meta) meta.setAttribute('content', isDark ? '#0f0f0f' : '#ffffff');
4335
})();
4436
</script>
4537
</head>

frontend/public/style.css

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ body {
33
margin: 0;
44
padding: 0;
55
font-family: "Inter", Helvetica, Arial, FreeSans, sans-serif;
6+
background-color: var(--studio-bg-page);
7+
color: var(--studio-text-page);
68
}
79

810
a {
911
text-decoration: none;
10-
color: #0e5887;
12+
color: var(--studio-link);
13+
}
14+
15+
a:hover {
16+
color: var(--studio-link-hover);
1117
}
1218

1319
.bold {
@@ -23,8 +29,9 @@ a {
2329
.tooltip .tooltiptext {
2430
visibility: hidden;
2531
width: 120px;
26-
background-color: black;
27-
color: #fff;
32+
background-color: var(--studio-tooltip-bg);
33+
color: var(--studio-tooltip-text);
34+
border: 1px solid var(--studio-tooltip-border);
2835
text-align: center;
2936
padding: 5px 0px;
3037
border-radius: 6px;
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* Theme variables for Mongoose Studio.
3+
* Use these variables in component CSS and in theme overrides so we can add
4+
* more themes (e.g. .theme-ocean) or role-based themes (e.g. data-theme="admin") later.
5+
*
6+
* Default theme: light. Switch by adding .dark on <html> (or future .theme-* classes).
7+
*/
8+
9+
/* -----------------------------------------------------------------------------
10+
* Light theme (default)
11+
* ----------------------------------------------------------------------------- */
12+
:root {
13+
color-scheme: light;
14+
15+
/* Page */
16+
--studio-bg-page: #ffffff;
17+
--studio-text-page: #111827;
18+
19+
/* Surfaces (cards, panels, nav) */
20+
--studio-bg-surface: #ffffff;
21+
--studio-bg-surface-hover: #f9fafb;
22+
--studio-bg-muted: #f9fafb;
23+
--studio-bg-muted-hover: #f3f4f6;
24+
--studio-bg-subtle: #e5e7eb;
25+
--studio-bg-subtle-hover: #d1d5db;
26+
--studio-bg-strong: #374151;
27+
--studio-bg-stronger: #1f2937;
28+
29+
/* Text */
30+
--studio-text-primary: #111827;
31+
--studio-text-secondary: #374151;
32+
--studio-text-muted: #6b7280;
33+
--studio-text-subtle: #9ca3af;
34+
35+
/* Borders */
36+
--studio-border: #e5e7eb;
37+
--studio-border-strong: #d1d5db;
38+
--studio-ring: rgba(17, 24, 39, 0.05);
39+
--studio-ring-strong: rgba(75, 85, 99, 0.4);
40+
41+
/* Links */
42+
--studio-link: #0e5887;
43+
--studio-link-hover: #0c4a6f;
44+
45+
/* Semantic (status) */
46+
--studio-bg-error: #fef2f2;
47+
--studio-bg-warning: #fefce8;
48+
--studio-bg-success: #f0fdf4;
49+
--studio-bg-info: #eff6ff;
50+
--studio-border-error: #fecaca;
51+
--studio-border-warning: #fde047;
52+
--studio-border-success: #bbf7d0;
53+
--studio-border-info: #bfdbfe;
54+
--studio-text-error: #b91c1c;
55+
--studio-text-success: #15803d;
56+
--studio-ring-success: rgba(34, 197, 94, 0.2);
57+
--studio-ring-muted: rgba(75, 85, 99, 0.2);
58+
59+
/* Tooltip */
60+
--studio-tooltip-bg: #000000;
61+
--studio-tooltip-text: #ffffff;
62+
--studio-tooltip-border: transparent;
63+
64+
/* Extended (code, menu, focus, brand, buttons) */
65+
--studio-code-bg: #f3f4f6;
66+
--studio-code-text: #111827;
67+
--studio-menu-bg: #ffffff;
68+
--studio-menu-hover: rgba(0, 0, 0, 0.05);
69+
--studio-menu-selected: rgba(0, 0, 0, 0.08);
70+
--studio-shadow: rgba(0, 0, 0, 0.1);
71+
--studio-focus-ring: #3b82f6;
72+
--studio-focus-ring-shadow: rgba(59, 130, 246, 0.2);
73+
--studio-brand-primary: #0e5887;
74+
--studio-brand-primary-hover: #0c4a6f;
75+
--studio-brand-primary-subtle: rgba(14, 88, 135, 0.1);
76+
--studio-btn-bg: #e5e7eb;
77+
--studio-btn-text-shadow: transparent;
78+
79+
/* Browser chrome (theme-color meta is set in JS; this is for reference/fallback) */
80+
--studio-theme-color: #ffffff;
81+
}
82+
83+
/* -----------------------------------------------------------------------------
84+
* Dark theme (your preferred dark mode colors)
85+
* Add class "dark" on <html> to enable.
86+
* ----------------------------------------------------------------------------- */
87+
.dark {
88+
color-scheme: dark;
89+
90+
/* Page – darker base for clear hierarchy */
91+
--studio-bg-page: #0f0f0f;
92+
--studio-text-page: #f5f5f5;
93+
94+
/* Surfaces – stepped contrast so nav/sidebar/content read clearly */
95+
--studio-bg-surface: #1c1c1e;
96+
--studio-bg-surface-hover: #2c2c2e;
97+
--studio-bg-muted: #252528;
98+
--studio-bg-muted-hover: #2c2c2e;
99+
--studio-bg-subtle: #3a3a3c;
100+
--studio-bg-subtle-hover: #48484a;
101+
--studio-bg-strong: #636366;
102+
--studio-bg-stronger: #1c1c1e;
103+
104+
/* Text – high contrast for readability */
105+
--studio-text-primary: #ffffff;
106+
--studio-text-secondary: #e8e8e8;
107+
--studio-text-muted: #b8b8bc;
108+
--studio-text-subtle: #a0a0a5;
109+
110+
/* Borders */
111+
--studio-border: #3a3a3c;
112+
--studio-border-strong: #48484a;
113+
--studio-ring: rgba(0, 0, 0, 0.4);
114+
--studio-ring-strong: rgba(99, 99, 102, 0.5);
115+
116+
/* Links */
117+
--studio-link: #64b5f6;
118+
--studio-link-hover: #90caf9;
119+
120+
/* Semantic (status) */
121+
--studio-bg-error: #450a0a;
122+
--studio-bg-warning: #422006;
123+
--studio-bg-success: #052e16;
124+
--studio-bg-info: #1e3a8a;
125+
--studio-border-error: #7f1d1d;
126+
--studio-border-warning: #854d0e;
127+
--studio-border-success: #14532d;
128+
--studio-border-info: #1e40af;
129+
--studio-text-error: #fca5a5;
130+
--studio-text-success: #86efac;
131+
--studio-ring-success: rgba(34, 197, 94, 0.3);
132+
--studio-ring-muted: rgba(75, 85, 99, 0.4);
133+
134+
/* Tooltip */
135+
--studio-tooltip-bg: #2c2c2e;
136+
--studio-tooltip-text: #f5f5f5;
137+
--studio-tooltip-border: #3a3a3c;
138+
139+
/* Extended (for nav, code, buttons, focus, brand) */
140+
--studio-code-bg: #252525;
141+
--studio-code-text: #e8e8e8;
142+
--studio-menu-bg: #252525;
143+
--studio-menu-hover: rgba(255, 255, 255, 0.1);
144+
--studio-menu-selected: rgba(255, 255, 255, 0.15);
145+
--studio-shadow: rgba(0, 0, 0, 0.3);
146+
--studio-focus-ring: #FFB4B4;
147+
--studio-focus-ring-shadow: rgba(255, 180, 180, 0.2);
148+
--studio-brand-primary: #FF5E5E;
149+
--studio-brand-primary-hover: #FF5555;
150+
--studio-brand-primary-subtle: rgba(255, 180, 180, 0.1);
151+
--studio-btn-bg: #444444;
152+
--studio-btn-text-shadow: #222222;
153+
154+
--studio-theme-color: #0f0f0f;
155+
}
156+
157+
/* Dark mode when using data-theme (same colors as .dark) */
158+
[data-theme="dark"] {
159+
color-scheme: dark;
160+
--studio-bg-page: #0f0f0f;
161+
--studio-text-page: #f5f5f5;
162+
--studio-bg-surface: #1c1c1e;
163+
--studio-bg-surface-hover: #2c2c2e;
164+
--studio-bg-muted: #252528;
165+
--studio-bg-muted-hover: #2c2c2e;
166+
--studio-bg-subtle: #3a3a3c;
167+
--studio-bg-subtle-hover: #48484a;
168+
--studio-bg-strong: #636366;
169+
--studio-bg-stronger: #1c1c1e;
170+
--studio-text-primary: #ffffff;
171+
--studio-text-secondary: #e8e8e8;
172+
--studio-text-muted: #b8b8bc;
173+
--studio-text-subtle: #a0a0a5;
174+
--studio-border: #3a3a3c;
175+
--studio-border-strong: #48484a;
176+
--studio-ring: rgba(0, 0, 0, 0.3);
177+
--studio-ring-strong: rgba(75, 85, 99, 0.4);
178+
--studio-link: #7BC3FF;
179+
--studio-link-hover: #8AD0FF;
180+
--studio-bg-error: #450a0a;
181+
--studio-bg-warning: #422006;
182+
--studio-bg-success: #052e16;
183+
--studio-bg-info: #1e3a8a;
184+
--studio-border-error: #7f1d1d;
185+
--studio-border-warning: #854d0e;
186+
--studio-border-success: #14532d;
187+
--studio-border-info: #1e40af;
188+
--studio-text-error: #fca5a5;
189+
--studio-text-success: #86efac;
190+
--studio-ring-success: rgba(34, 197, 94, 0.3);
191+
--studio-ring-muted: rgba(75, 85, 99, 0.4);
192+
--studio-tooltip-bg: #252525;
193+
--studio-tooltip-text: #e8e8e8;
194+
--studio-tooltip-border: #444444;
195+
--studio-code-bg: #252525;
196+
--studio-code-text: #e8e8e8;
197+
--studio-menu-bg: #252525;
198+
--studio-menu-hover: rgba(255, 255, 255, 0.1);
199+
--studio-menu-selected: rgba(255, 255, 255, 0.15);
200+
--studio-shadow: rgba(0, 0, 0, 0.3);
201+
--studio-focus-ring: #FFB4B4;
202+
--studio-focus-ring-shadow: rgba(255, 180, 180, 0.2);
203+
--studio-brand-primary: #FF5E5E;
204+
--studio-brand-primary-hover: #FF5555;
205+
--studio-brand-primary-subtle: rgba(255, 180, 180, 0.1);
206+
--studio-btn-bg: #444444;
207+
--studio-btn-text-shadow: #222222;
208+
--studio-theme-color: #0f0f0f;
209+
}
210+
211+
/*
212+
* Future: add more themes the same way, e.g.:
213+
*
214+
* .theme-ocean {
215+
* --studio-bg-page: #f0f9ff;
216+
* --studio-link: #0369a1;
217+
* ...
218+
* }
219+
*
220+
* Or role-based (set class or data-theme from backend):
221+
*
222+
* [data-theme="admin"] {
223+
* --studio-link: #7c3aed;
224+
* ...
225+
* }
226+
*/

frontend/src/chat/chat-message-script/chat-message-script.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="relative border rounded bg-white my-1 text-black text-sm overflow-hidden">
1+
<div class="chat-message-script relative border rounded bg-white my-1 text-black text-sm overflow-hidden">
22
<div class="flex border-b py-1 pl-1 text-xs font-medium bg-white">
33
<button
44
class="px-4 py-1 border-r border-gray-300 text-gray-700 font-semibold transition-colors duration-200 focus:outline-none"

frontend/src/dashboard-result/dashboard-map/dashboard-map.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,25 @@
33

44
const template = require('./dashboard-map.html');
55

6+
function getMapTileLayerOptions() {
7+
const isDark = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
8+
return isDark
9+
? { url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>', subdomains: 'abcd', maxZoom: 20 }
10+
: { url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: '&copy; OpenStreetMap contributors' };
11+
}
12+
613
module.exports = app => app.component('dashboard-map', {
714
template: template,
815
props: ['value', 'height'],
16+
data() {
17+
return { _map: null, _tileLayer: null };
18+
},
919
mounted() {
1020
const fc = this.value.$featureCollection.featureCollection || this.value.$featureCollection;
1121
const map = L.map(this.$refs.map).setView([0, 0], 1);
12-
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
13-
attribution: '&copy; OpenStreetMap contributors'
14-
}).addTo(map);
22+
this._map = map;
23+
const opts = getMapTileLayerOptions();
24+
this._tileLayer = L.tileLayer(opts.url, opts).addTo(map);
1525
const layer = L.geoJSON(fc).addTo(map);
1626

1727
this.$nextTick(() => {
@@ -21,6 +31,20 @@ module.exports = app => app.component('dashboard-map', {
2131
map.fitBounds(bounds);
2232
}
2333
});
34+
this._onStudioThemeChanged = () => this._updateMapTileLayer();
35+
document.documentElement.addEventListener('studio-theme-changed', this._onStudioThemeChanged);
36+
},
37+
beforeDestroy() {
38+
document.documentElement.removeEventListener('studio-theme-changed', this._onStudioThemeChanged);
39+
},
40+
methods: {
41+
_updateMapTileLayer() {
42+
if (!this._map || !this._tileLayer || typeof L === 'undefined') return;
43+
this._tileLayer.remove();
44+
this._tileLayer = null;
45+
const opts = getMapTileLayerOptions();
46+
this._tileLayer = L.tileLayer(opts.url, opts).addTo(this._map);
47+
}
2448
},
2549
computed: {
2650
mapStyle() {

frontend/src/dashboard/dashboard.html

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<div class="dashboard px-1">
1+
<div class="dashboard-root">
2+
<div class="dashboard px-1">
23
<div v-if="status === 'loading'" class="max-w-5xl mx-auto text-center">
34
<img src="images/loader.gif" class="inline mt-10">
45
</div>
@@ -15,7 +16,7 @@ <h2 class="mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink">{{title}}<
1516
</button>
1617

1718
<async-button
18-
@click="evaluateDashboard"
19+
@click="() => evaluateDashboard()"
1920
type="button"
2021
:disabled="status === 'evaluating'"
2122
class="flex items-center rounded-md bg-ultramarine-600 px-4 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600"
@@ -63,7 +64,7 @@ <h2 class="mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink">{{title}}<
6364
<div class="flex flex-col items-center justify-center py-8">
6465
<p class="text-gray-700 text-base mb-4">This dashboard hasn't been evaluated yet.</p>
6566
<async-button
66-
@click="evaluateDashboard"
67+
@click="() => evaluateDashboard()"
6768
type="button"
6869
:disabled="status === 'evaluating'"
6970
class="rounded-md bg-ultramarine-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600"
@@ -116,9 +117,9 @@ <h3 class="text-sm font-medium text-red-800">{{dashboardResult.error.message ||
116117
<div v-if="!dashboard && status !== 'loading'">
117118
No dashboard with the given id could be found.
118119
</div>
119-
</div>
120+
</div>
120121

121-
<modal
122+
<modal
122123
v-if="showDetailModal"
123124
containerClass="!h-[90vh] !w-[90vw]"
124125
role="dialog"
@@ -138,3 +139,4 @@ <h3 class="text-sm font-medium text-red-800">{{dashboardResult.error.message ||
138139
</div>
139140
</template>
140141
</modal>
142+
</div>

0 commit comments

Comments
 (0)