[ADD] runbot_merge: color theme switcher

Uses localStorage rather than the odoo backend cookie because
Odoo *requires* the cookie, it can't fallback on the system theme, and
we might want a different color theme on the frontend and backend
since the frontend dark theme is pretty half-assed.

Also load the file by hand, as adding it to `assets_frontend` causes a
flash of system color theme. It would probably be possible to create
an asset which is not deferred or lazy (but wouldn't be async either
which is a shame), but I can't be arsed.

Part of #1088
This commit is contained in:
Xavier Morel 2025-03-12 15:10:26 +01:00
parent 9138aae3d8
commit 6f65836a22
3 changed files with 70 additions and 3 deletions

View File

@ -1,6 +1,6 @@
// resets a bunch of CSS rules to either `inherit` color or use CSS variables,
// such that they properly follow CSS variables
:root {
:root, :root.light {
color-scheme: light dark;
// dunno why it's not global
@ -17,11 +17,11 @@
// adjusting the conversion just set the value we want
--danger-bg-rgb: 242, 222, 222;
}
@function invlight($value) {
@return hsl(hue($value), saturation($value), 100% - lightness($value));
}
@media (prefers-color-scheme: dark) {
:root {
@mixin darkrules {
$ibc: invlight($body-color);
--body-color: #{$ibc};
--body-color-rgb: #{to-rgb($ibc)};
@ -41,8 +41,17 @@
))};
}
--danger-bg-rgb: 41, 10, 10;
}
:root.dark {
@include darkrules;
}
@media (prefers-color-scheme: dark) {
:root:not(.light) {
@include darkrules;
}
}
body {
font-family: inherit;
}

View File

@ -0,0 +1,42 @@
function setColorScheme(t) {
const classes = document.documentElement.classList;
classes.remove('light', 'dark');
const buttons = document.querySelectorAll('.theme-toggle button');
for(const button of buttons) {
button.classList.toggle(
'active',
(t === 'light' && button.classList.contains('fa-sun-o'))
|| (t === 'dark' && button.classList.contains('fa-moon-o'))
|| (t !== 'light' && t !== 'dark' && button.classList.contains('fa-ban'))
);
}
switch (t) {
case 'light': case 'dark':
classes.add(t);
window.localStorage.setItem('color-scheme', t);
break;
default:
window.localStorage.removeItem('color-scheme');
}
}
window.addEventListener("click", (e) => {
const target = e.target;
if (target.matches(".btn-group.theme-toggle button")) {
setColorScheme(
target.classList.contains('fa-sun-o') ? 'light' :
target.classList.contains('fa-moon-o') ? 'dark' :
null
);
}
});
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", (e) => {
setColorScheme(window.localStorage.getItem('color-scheme'));
});
} else {
setColorScheme(window.localStorage.getItem('color-scheme'));
}

View File

@ -640,4 +640,20 @@ action = batches
</tbody>
</table>
</template>
<template id="theme-script" inherit_id="website.layout">
<xpath expr="//head" position="inside">
<script type="text/javascript"
src="/runbot_merge/static/src/js/runbot_merge.js"
async="async"/>
</xpath>
</template>
<template id="theme-toggle" inherit_id="website.placeholder_header_call_to_action">
<xpath expr="." position="inside">
<div class="btn-group btn-group-toggle theme-toggle">
<button class="btn btn-outline-secondary fa fa-sun-o"/>
<button class="btn btn-outline-secondary fa fa-moon-o"/>
<button class="btn btn-outline-secondary fa fa-ban active"/>
</div>
</xpath>
</template>
</odoo>