✨ Add theme support
This commit is contained in:
25
src/App.vue
25
src/App.vue
@ -4,8 +4,17 @@ import TitleBar from "./components/titlebar-element.vue";
|
||||
import BottomNavbar from "./components/bottom-navbar.vue";
|
||||
import DateSelector from "./components/date-selector.vue";
|
||||
import LoadingElement from "./components/loading-element.vue";
|
||||
import { loading } from "./store";
|
||||
import { computed } from "vue";
|
||||
import { loading, theme } from "./store";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
const autoThemes = { true: "dark", false: "light" };
|
||||
const autoTheme = ref("dark");
|
||||
const colorSchemeMedia = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
autoTheme.value = autoThemes[colorSchemeMedia.matches];
|
||||
colorSchemeMedia.addEventListener(
|
||||
"change",
|
||||
(e) => (autoTheme.value = autoThemes[e.matches])
|
||||
);
|
||||
|
||||
const route = useRoute();
|
||||
const routeName = computed(() => route.name);
|
||||
@ -17,7 +26,10 @@ const isDataView = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app">
|
||||
<div
|
||||
class="app"
|
||||
:class="theme == 'auto' ? `theme-${autoTheme}` : `theme-${theme}`"
|
||||
>
|
||||
<TitleBar />
|
||||
<DateSelector v-show="isDataView" />
|
||||
<div class="center">
|
||||
@ -32,6 +44,7 @@ const isDataView = computed(() => {
|
||||
|
||||
<style>
|
||||
@import "./assets/base.css";
|
||||
@import "./assets/themes.css";
|
||||
|
||||
html,
|
||||
body {
|
||||
@ -42,14 +55,14 @@ body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color-scheme: dark;
|
||||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
.app {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
.center {
|
||||
|
@ -1,30 +1,3 @@
|
||||
:root {
|
||||
--bg-color: #353535;
|
||||
--element-color: #333030;
|
||||
--element-color-hover: #292424;
|
||||
--element-border-input: #4e7a3a;
|
||||
--element-border-focus: #9ac982;
|
||||
--element-border-action: #1f5b63;
|
||||
--text-color: #bdbdbd;
|
||||
--font-family: "sourcesanspro";
|
||||
--titlebar-color: #212121;
|
||||
--titlebar-element-active-color: #466439;
|
||||
--titlebar-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.2);
|
||||
--bottomnav-color: #555555;
|
||||
--bottomnav-icon-color: #c7c7c7;
|
||||
--bottomnav-icon-active-color: #456c47;
|
||||
--bottomnav-active-color: #7ca74b;
|
||||
--bottomnav-shadow: 5px 7px 19px 0px rgba(0, 0, 0, 0.25);
|
||||
--loader-color: #7ca74b;
|
||||
--substitution-background-change: #14587e;
|
||||
--substitution-background-cancellation: #7d2b2d;
|
||||
--substitution-background-addition: #476331;
|
||||
--substitution-background-deletion: #7d2b2d;
|
||||
--substitution-background-unchanged: #26272a;
|
||||
--timetable-trust-warning-border: #b71c1c;
|
||||
--timetable-trust-warning-background: #412727;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "sourcesanspro";
|
||||
font-style: "normal";
|
||||
|
53
src/assets/themes.css
Normal file
53
src/assets/themes.css
Normal file
@ -0,0 +1,53 @@
|
||||
.app.theme-dark {
|
||||
--bg-color: #353535;
|
||||
--element-color: #333030;
|
||||
--element-color-hover: #292424;
|
||||
--element-border-input: #4e7a3a;
|
||||
--element-border-focus: #9ac982;
|
||||
--element-border-action: #1f5b63;
|
||||
--text-color: #bdbdbd;
|
||||
--font-family: "sourcesanspro";
|
||||
--titlebar-color: #212121;
|
||||
--titlebar-element-active-color: #466439;
|
||||
--titlebar-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.2);
|
||||
--bottomnav-color: #555555;
|
||||
--bottomnav-icon-color: #c7c7c7;
|
||||
--bottomnav-icon-active-color: #456c47;
|
||||
--bottomnav-active-color: #7ca74b;
|
||||
--bottomnav-shadow: 5px 7px 19px 0px rgba(0, 0, 0, 0.25);
|
||||
--loader-color: #7ca74b;
|
||||
--substitution-background-change: #095079;
|
||||
--substitution-background-cancellation: #7d2b2d;
|
||||
--substitution-background-addition: #375c1d;
|
||||
--substitution-background-deletion: #7d2b2d;
|
||||
--substitution-background-unchanged: #26272a;
|
||||
--timetable-trust-warning-border: #b71c1c;
|
||||
--timetable-trust-warning-background: #412727;
|
||||
}
|
||||
|
||||
.app.theme-light {
|
||||
--bg-color: #e0e0e0;
|
||||
--element-color: #bdbdbd;
|
||||
--element-color-hover: #ada9a9;
|
||||
--element-border-input: #4caf50;
|
||||
--element-border-focus: #7ba764;
|
||||
--element-border-action: #3f51b5;
|
||||
--text-color: #353131;
|
||||
--font-family: "sourcesanspro";
|
||||
--titlebar-color: #d3d4d3;
|
||||
--titlebar-element-active-color: #97af98;
|
||||
--titlebar-shadow: 0px 0px 10px 5px rgba(0, 0, 0, 0.2);
|
||||
--bottomnav-color: #b1c5b2;
|
||||
--bottomnav-icon-color: #584f4f;
|
||||
--bottomnav-icon-active-color: #456c47;
|
||||
--bottomnav-active-color: #99b677;
|
||||
--bottomnav-shadow: 5px 7px 19px 0px rgba(0, 0, 0, 0.25);
|
||||
--loader-color: #7ca74b;
|
||||
--substitution-background-change: #9bb7c7;
|
||||
--substitution-background-cancellation: #e4a7a9;
|
||||
--substitution-background-addition: #b0d396;
|
||||
--substitution-background-deletion: #e4a7a9;
|
||||
--substitution-background-unchanged: #cecccc;
|
||||
--timetable-trust-warning-border: #b71c1c;
|
||||
--timetable-trust-warning-background: #dabcbc;
|
||||
}
|
@ -76,5 +76,21 @@ span.description {
|
||||
|
||||
select {
|
||||
margin-top: 15px;
|
||||
padding: 5px 0px;
|
||||
outline: none;
|
||||
border: 2px solid var(--element-border-input);
|
||||
border-radius: 5px;
|
||||
background-color: var(--element-color);
|
||||
transition: 0.2s;
|
||||
transition-property: background-color border-color;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
select:hover {
|
||||
background-color: var(--element-color-hover);
|
||||
}
|
||||
|
||||
select:focus {
|
||||
border-color: var(--element-border-focus);
|
||||
}
|
||||
</style>
|
||||
|
@ -11,6 +11,7 @@ export const timetableGroups = ref(
|
||||
JSON.parse(localStorage.getItem("timetableGroups") || "[]")
|
||||
);
|
||||
export const language = ref(localStorage.getItem("lang") || "en");
|
||||
export const theme = ref(localStorage.getItem("theme") || "auto");
|
||||
|
||||
watch(classFilter, (newValue) => {
|
||||
localStorage.setItem("classFilter", newValue);
|
||||
@ -24,6 +25,9 @@ watch(language, (newValue) => {
|
||||
localStorage.setItem("lang", newValue);
|
||||
location.reload();
|
||||
});
|
||||
watch(theme, (newValue) => {
|
||||
localStorage.setItem("theme", newValue);
|
||||
});
|
||||
|
||||
// Set this to a positive or negative integer
|
||||
// to change selectedDate by this number
|
||||
|
@ -13,6 +13,7 @@ export const strings = {
|
||||
timetableGroups: "Timetable Groups",
|
||||
language: "Language",
|
||||
about: "About",
|
||||
theme: "Theme",
|
||||
},
|
||||
text: {
|
||||
filtering:
|
||||
@ -22,10 +23,17 @@ export const strings = {
|
||||
language: "Change the language of all texts in the application.",
|
||||
about:
|
||||
"This Tool queries and parses the latest substitution-plan data every minute. The correctness of the data can in no way be guaranteed, so please check the data against the official plan if something seems wrong! Due to the format of the plan files, it it sometimes not easily possible to extract the correct data, so the plan displayed here may not be correct.",
|
||||
theme:
|
||||
"Select a Theme to change the colors of the app. The 'Auto' option selects a theme based on your system preferences.",
|
||||
},
|
||||
other: "Other",
|
||||
none: "None",
|
||||
version: "Version",
|
||||
theme: {
|
||||
auto: "Auto",
|
||||
dark: "Dark",
|
||||
light: "Light",
|
||||
},
|
||||
},
|
||||
timetable: {
|
||||
warning: "Warning:",
|
||||
@ -84,6 +92,7 @@ export const strings = {
|
||||
timetableGroups: "Stundenplan-Gruppen",
|
||||
language: "Sprache",
|
||||
about: "Über diese Anwendung",
|
||||
theme: "Farbschema",
|
||||
},
|
||||
text: {
|
||||
filtering:
|
||||
@ -93,10 +102,17 @@ export const strings = {
|
||||
language: "Ändere die Sprache aller Texte dieser Anwendung.",
|
||||
about:
|
||||
"Diese Anwendung fragt jede Minute die neusten Vertretungsplan-Daten an und verarbeitet sie, um sie dir schöner und besser lesbar anzuzeigen. Die Richtigkeit dieser Daten kann nicht garantiert werden, da es manchmal kompliziert ist, die richtigen Daten zu extrahieren. Wenn etwas nicht richtig aussieht, überprüfe es bitte auf dem offiziellen Plan!",
|
||||
theme:
|
||||
"Wähle ein Farbschema aus, um die Farben dieser Anwendung anzupassen. Die Option 'Automatisch' wählt ein Farbschema basierend auf den Einstellungen deines Systems aus.",
|
||||
},
|
||||
other: "Andere",
|
||||
none: "Keine",
|
||||
version: "Version",
|
||||
theme: {
|
||||
auto: "Automatisch",
|
||||
dark: "Dunkel",
|
||||
light: "Hell",
|
||||
},
|
||||
},
|
||||
timetable: {
|
||||
warning: "Warnung:",
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
possibleTimetableGroups,
|
||||
timetableGroups,
|
||||
language,
|
||||
theme,
|
||||
} from "../store";
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
@ -54,6 +55,16 @@ const gitHash = GITVERSION;
|
||||
</select>
|
||||
<div class="spacer"></div>
|
||||
|
||||
<!-- Theme -->
|
||||
<h2>{{ $t("settings.heading.theme") }}</h2>
|
||||
<p>{{ $t("settings.text.theme") }}</p>
|
||||
<select v-model="theme">
|
||||
<option value="auto">{{ $t("settings.theme.auto") }}</option>
|
||||
<option value="dark">{{ $t("settings.theme.dark") }}</option>
|
||||
<option value="light">{{ $t("settings.theme.light") }}</option>
|
||||
</select>
|
||||
<div class="spacer"></div>
|
||||
|
||||
<!-- About -->
|
||||
<h2>{{ $t("settings.heading.about") }}</h2>
|
||||
<p>{{ $t("settings.text.about") }}</p>
|
||||
@ -87,6 +98,7 @@ select {
|
||||
background-color: var(--element-color);
|
||||
transition: 0.2s;
|
||||
transition-property: background-color border-color;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
select:hover {
|
||||
|
Reference in New Issue
Block a user