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;
}
.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,
.btn-link:hover {
color: #0080d4;
@@ -521,6 +535,39 @@ a,
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 */
.indicator-enter-active, .indicator-leave-active {
transition: all .3s;

View File

@@ -42,6 +42,20 @@ export default {
})
this.updateMetaTheme(app.settings.theme_name)
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() {
setupKeybindings(this)
@@ -276,6 +290,10 @@ export default {
},
methods: {
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]
},
refreshStats: function(loopMode) {

View File

@@ -46,14 +46,13 @@
<header class="dropdown-header" role="heading" aria-level="2">{{ $t('theme') }}</header>
<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"
:title="t"
:aria-label="t"
:aria-pressed="theme.name == t"
@click.stop="theme.name = t"
v-for="t in ['light', 'sepia', 'night']">
<v-icon v-if="theme.name == t" name="check" />
v-for="t in ['light', 'sepia', 'night', 'system']">
</button>
</div>