Add manual dark/light switch (#3901)

* Add manual dark/light switch

* Improve color theme labels
This commit is contained in:
Michael Geers 2022-08-01 10:15:27 +02:00 • committed by GitHub
parent 47287956a6
commit a3aba01adc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 219 additions and 143 deletions

View file

@ -60,18 +60,16 @@
"Segoe UI Symbol", "Noto Color Emoji";
}
@media (--dark-mode) {
:root {
--evcc-grid: var(--bs-gray-medium);
--evcc-background: var(--bs-gray-deep);
--evcc-box: var(--bs-gray-dark);
--evcc-default-text: var(--bs-white);
--evcc-gray: var(--bs-gray-light);
--evcc-accent1: var(--evcc-yellow);
--evcc-accent2: var(--evcc-dark-green);
--evcc-accent3: var(--evcc-darker-green);
--bs-primary: var(--evcc-dark-green);
}
:root.dark {
--evcc-grid: var(--bs-gray-medium);
--evcc-background: var(--bs-gray-deep);
--evcc-box: var(--bs-gray-dark);
--evcc-default-text: var(--bs-white);
--evcc-gray: var(--bs-gray-light);
--evcc-accent1: var(--evcc-yellow);
--evcc-accent2: var(--evcc-dark-green);
--evcc-accent3: var(--evcc-darker-green);
--bs-primary: var(--evcc-dark-green);
}
html {
@ -80,6 +78,10 @@ html {
overflow-x: hidden;
}
html.no-transitions * {
transition-duration: 0ms !important;
}
body {
background-color: var(--evcc-background);
color: var(--evcc-default-text);

View file

@ -10,6 +10,7 @@ import VueNumber from "vue-number-animation";
import router from "./router";
import i18n from "./i18n";
import featureflags from "./featureflags";
import { watchThemeChanges } from "./theme";
smoothscroll.polyfill();
@ -76,10 +77,4 @@ window.setInterval(function () {
api.get("health").then(window.app.setOnline).catch(window.app.setOffline);
}, 5000);
const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)");
isDarkMode.addEventListener("change", updateThemeColor);
function updateThemeColor() {
const $el = document.querySelector("meta[name=theme-color]");
$el.setAttribute("content", isDarkMode.matches ? "#020318" : "#f3f3f7");
}
updateThemeColor();
watchThemeChanges();

View file

@ -217,11 +217,10 @@ export default {
background-color: var(--evcc-grid);
color: var(--bs-white);
}
@media (--dark-mode) {
.grid-import {
color: var(--bs-dark);
}
html.dark .grid-import {
color: var(--bs-dark);
}
.self-consumption {
background-color: var(--evcc-self);
color: var(--bs-dark);

View file

@ -31,9 +31,7 @@ export default {
.letter {
fill: #18191a;
}
@media (--dark-mode) {
.letter {
fill: var(--bs-white);
}
html.dark .letter {
fill: var(--bs-white);
}
</style>

View file

@ -53,11 +53,10 @@ export default {
border-radius: 1px;
overflow: hidden;
}
@media (--dark-mode) {
.phase {
background-color: var(--bs-gray-bright);
}
html.dark .phase {
background-color: var(--bs-gray-bright);
}
.phase.inactive {
display: none;
}

View file

@ -38,6 +38,11 @@
{{ $t("header.about") }}
</a>
</li>
<li>
<button type="button" class="dropdown-item" @click.stop="toggleTheme">
{{ $t(`header.theme.${theme}`) }}
</button>
</li>
<template v-if="providerLogins.length > 0">
<li><hr class="dropdown-divider" /></li>
<li>
@ -64,7 +69,9 @@
<script>
import "@h2d2/shopicons/es/regular/menu";
import baseAPI from "../baseapi";
import { getThemePreference, setThemePreference, THEMES } from "../theme";
export default {
name: "TopNavigation",
@ -76,6 +83,9 @@ export default {
},
},
},
data: function () {
return { theme: getThemePreference() };
},
computed: {
logoutCount() {
return this.providerLogins.filter((login) => !login.loggedIn).length;
@ -90,6 +100,12 @@ export default {
},
},
methods: {
toggleTheme: function () {
const currentIndex = THEMES.indexOf(this.theme);
const nextIndex = currentIndex < THEMES.length - 1 ? currentIndex + 1 : 0;
this.theme = THEMES[nextIndex];
setThemePreference(this.theme);
},
handleProviderAuthorization: async function (provider) {
if (!provider.loggedIn) {
baseAPI.post(provider.loginPath).then(function (response) {

View file

@ -5,6 +5,11 @@ export default {
github: "GitHub",
login: "Fahrzeug Logins",
about: "Über evcc",
theme: {
auto: "Design: System",
light: "Design: Hell",
dark: "Design: Dunkel",
},
},
footer: {
version: {

View file

@ -5,6 +5,11 @@ export default {
github: "GitHub",
login: "Vehicle Logins",
about: "About evcc",
theme: {
auto: "Design: System",
light: "Design: Light",
dark: "Design: Dark",
},
},
footer: {
version: {

57
assets/js/theme.js Normal file
View file

@ -0,0 +1,57 @@
const darkModeMatcher = window.matchMedia("(prefers-color-scheme: dark)");
const THEME_AUTO = "auto";
const THEME_LIGHT = "light";
const THEME_DARK = "dark";
export const THEMES = [THEME_AUTO, THEME_LIGHT, THEME_DARK];
const LOCAL_STORAGE_KEY = "theme";
export function getThemePreference() {
try {
const theme = window.localStorage[LOCAL_STORAGE_KEY];
if (THEMES.includes(theme)) {
return theme;
}
} catch (e) {
console.error("unable to read theme from localStorage", e);
}
return THEME_AUTO;
}
export function setThemePreference(theme) {
console.log({ theme });
if (!THEMES.includes(theme)) {
return;
}
try {
window.localStorage[LOCAL_STORAGE_KEY] = theme;
updateTheme();
} catch (e) {
console.error("unable to write theme to localStorage", e);
}
}
function updateTheme() {
let theme = getThemePreference();
if (theme === THEME_AUTO) {
theme = darkModeMatcher.matches ? THEME_DARK : THEME_LIGHT;
}
// update iOS title bar color
const themeColors = { light: "#f3f3f7", dark: "#020318" };
document.querySelector("meta[name=theme-color]").setAttribute("content", themeColors[theme]);
// toggle the class on html root
const $html = document.querySelector(":root");
$html.classList.add("no-transitions");
$html.classList.toggle("dark", theme === THEME_DARK);
window.requestAnimationFrame(function () {
$html.classList.remove("no-transitions");
});
}
export function watchThemeChanges() {
darkModeMatcher.addEventListener("change", updateTheme);
updateTheme();
}

File diff suppressed because one or more lines are too long

109
dist/assets/index.aadc69fd.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View file

@ -20,8 +20,8 @@
<meta name="theme-color" content="#020318" />
<title>evcc</title>
<script type="module" crossorigin src="./assets/index.f9e9d211.js"></script>
<link rel="stylesheet" href="./assets/index.36f32821.css">
<script type="module" crossorigin src="./assets/index.aadc69fd.js"></script>
<link rel="stylesheet" href="./assets/index.78e2f4a8.css">
</head>
<body>
<script>