frontend: system theme: auto light/dark mode

This commit is contained in:
nkanaev
2026-07-13 00:24:27 +01:00
parent eb27f21fd2
commit 61bf14e9a3
3 changed files with 67 additions and 3 deletions

View File

@@ -447,6 +447,20 @@ button.theme-light {
background-color: #fff !important; background-color: #fff !important;
} }
.theme-swatch {
padding: 0;
border: none;
height: 2.375rem;
}
.theme-swatch.theme-system {
background-image: linear-gradient(135deg, #fff 0, #fff 35%, #0e0e0e 65%, #0e0e0e 100%);
}
.theme-swatch[aria-pressed="true"] {
border: 0.3rem solid #0080d4;
}
a, a,
.btn-link:hover { .btn-link:hover {
color: #0080d4; color: #0080d4;
@@ -521,6 +535,39 @@ a,
border-color: #1a1a1a; border-color: #1a1a1a;
} }
/* theme: system follows the system color scheme */
@media (prefers-color-scheme: dark) {
.theme-system,
.theme-system .btn-default,
.theme-system .dropdown-menu,
.theme-system .dropdown-item,
.theme-system .form-control,
.theme-system .modal-content,
.theme-system .toolbar-search {
color: #d1d1d1;
background-color: #0e0e0e;
}
.theme-system .content hr,
.theme-system .content pre,
.theme-system .border-right,
.theme-system .border-top,
.theme-system .dropdown-divider {
border-color: #1a1a1a !important;
}
.theme-system .selectgroup-label:hover,
.theme-system .dropdown-item:hover,
.theme-system .toolbar-item:hover,
.theme-system .toolbar-search:hover,
.theme-system .toolbar-search:focus {
background-color: #1a1a1a;
}
.theme-system .dropdown-menu,
.theme-system .modal-content {
border-color: #1a1a1a !important;
}
}
/* animation */ /* animation */
.indicator-enter-active, .indicator-leave-active { .indicator-enter-active, .indicator-leave-active {
transition: all .3s; transition: all .3s;

View File

@@ -42,6 +42,20 @@ export default {
}) })
this.updateMetaTheme(app.settings.theme_name) this.updateMetaTheme(app.settings.theme_name)
this.$setLang(app.settings.language) this.$setLang(app.settings.language)
// keep the theme-color meta tag in sync when the OS color scheme changes
if (window.matchMedia) {
this._colorSchemeMql = window.matchMedia('(prefers-color-scheme: dark)')
this._colorSchemeHandler = function() {
this.updateMetaTheme(this.theme.name)
}.bind(this)
this._colorSchemeMql.addEventListener('change', this._colorSchemeHandler)
}
},
beforeDestroy: function() {
if (this._colorSchemeMql) {
this._colorSchemeMql.removeEventListener('change', this._colorSchemeHandler)
}
}, },
mounted: function() { mounted: function() {
setupKeybindings(this) setupKeybindings(this)
@@ -276,6 +290,10 @@ export default {
}, },
methods: { methods: {
updateMetaTheme: function(theme) { updateMetaTheme: function(theme) {
if (theme == 'system') {
var dark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
theme = dark ? 'night' : 'light'
}
document.querySelector("meta[name='theme-color']").content = this.themeColors[theme] document.querySelector("meta[name='theme-color']").content = this.themeColors[theme]
}, },
refreshStats: function(loopMode) { refreshStats: function(loopMode) {

View File

@@ -46,14 +46,13 @@
<header class="dropdown-header" role="heading" aria-level="2">{{ $t('theme') }}</header> <header class="dropdown-header" role="heading" aria-level="2">{{ $t('theme') }}</header>
<div class="row text-center m-0"> <div class="row text-center m-0">
<button class="btn btn-link col-4 px-0 rounded-0" <button class="btn btn-link theme-swatch col-3 px-0 rounded-0"
:class="'theme-'+t" :class="'theme-'+t"
:title="t" :title="t"
:aria-label="t" :aria-label="t"
:aria-pressed="theme.name == t" :aria-pressed="theme.name == t"
@click.stop="theme.name = t" @click.stop="theme.name = t"
v-for="t in ['light', 'sepia', 'night']"> v-for="t in ['light', 'sepia', 'night', 'system']">
<v-icon v-if="theme.name == t" name="check" />
</button> </button>
</div> </div>