This commit is contained in:
Avris 2021-06-15 12:57:50 +02:00
parent a36446978a
commit 5a5c0e625e
7 changed files with 307 additions and 1 deletions

235
assets/dark.scss Normal file
View File

@ -0,0 +1,235 @@
/* https://www.cssscript.com/dark-mode-switcher-for-bootstrap-5/ */
@import "variables";
body[data-theme="dark"] {
background: initial !important;
background-color: $dark !important;
color: $light;
a { color: lighten($primary, 40%); }
a:hover { color: lighten($primary, 30%); }
.text-dark { color: $light !important; }
.btn-outline-primary { color: $light; &:hover {color: $light;}}
/* BUTTONS */
.btn-link { color: #fff; }
.btn-close { filter: invert(1) grayscale(100%) brightness(200%); }
.btn-dark { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; }
.btn-dark:hover { color: #000; background-color: #f9fafb; border-color: #f9fafb; }
.btn-check:focus + .btn-dark,
.btn-dark:focus { color: #000; background-color: #f9fafb; border-color: #f9fafb; box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); }
.btn-check:checked + .btn-dark,
.btn-check:active + .btn-dark,
.btn-dark:active,
.btn-dark.active,
.show > .btn-dark.dropdown-toggle { color: #000; background-color: #f9fafb; border-color: #f9fafb; }
.btn-check:checked + .btn-dark:focus,
.btn-check:active + .btn-dark:focus,
.btn-dark:active:focus,
.btn-dark.active:focus,
.show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); }
.btn-dark:disabled,
.btn-dark.disabled { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; }
.btn-light { color: #fff; background-color: #212529; border-color: #212529; }
.btn-light:hover { color: #fff; background-color: #1c1f23; border-color: #1a1e21; }
.btn-check:focus + .btn-light,
.btn-light:focus { color: #fff; background-color: #1c1f23; border-color: #1a1e21; box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); }
.btn-check:checked + .btn-light,
.btn-check:active + .btn-light,
.btn-light:active,
.btn-light.active,
.show > .btn-light.dropdown-toggle { color: #fff; background-color: #1a1e21; border-color: #191c1f; }
.btn-check:checked + .btn-light:focus,
.btn-check:active + .btn-light:focus,
.btn-light:active:focus,
.btn-light.active:focus,
.show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); }
.btn-light:disabled,
.btn-light.disabled { color: #fff; background-color: #212529; border-color: #212529; }
.btn-outline-dark { color: #f8f9fa; border-color: #f8f9fa; }
.btn-outline-dark:hover { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; }
.btn-check:focus + .btn-outline-dark,
.btn-outline-dark:focus { box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); }
.btn-check:checked + .btn-outline-dark,
.btn-check:active + .btn-outline-dark,
.btn-outline-dark:active,
.btn-outline-dark.active,
.btn-outline-dark.dropdown-toggle.show { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; }
.btn-check:checked + .btn-outline-dark:focus,
.btn-check:active + .btn-outline-dark:focus,
.btn-outline-dark:active:focus,
.btn-outline-dark.active:focus,
.btn-outline-dark.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); }
.btn-outline-dark:disabled,
.btn-outline-dark.disabled { color: #f8f9fa; background-color: transparent; }
.btn-outline-light { color: #212529; border-color: #212529; }
.btn-outline-light:hover { color: #fff; background-color: #212529; border-color: #212529; }
.btn-check:focus + .btn-outline-light,
.btn-outline-light:focus { box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); }
.btn-check:checked + .btn-outline-light,
.btn-check:active + .btn-outline-light,
.btn-outline-light:active,
.btn-outline-light.active,
.btn-outline-light.dropdown-toggle.show { color: #fff; background-color: #212529; border-color: #212529; }
.btn-check:checked + .btn-outline-light:focus,
.btn-check:active + .btn-outline-light:focus,
.btn-outline-light:active:focus,
.btn-outline-light.active:focus,
.btn-outline-light.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); }
.btn-outline-light:disabled,
.btn-outline-light.disabled { color: #212529; background-color: transparent; }
/* DROPDOWNS */
.dropdown-menu { color: #dee2e6; background-color: #343a40; border-color: rgba(0, 0, 0, 0.15); }
.dropdown-menu .dropdown-item { color: #dee2e6; }
.dropdown-menu .dropdown-item:hover,
.dropdown-menu .dropdown-item:focus { color: #fff; background-color: rgba(255, 255, 255, 0.15); }
.dropdown-menu .dropdown-item.active,
.dropdown-menu .dropdown-item:active { color: #fff; background-color: #0d6efd; }
.dropdown-menu .dropdown-item.disabled,
.dropdown-menu .dropdown-item:disabled { color: #adb5bd; }
.dropdown-menu .dropdown-divider { border-color: rgba(0, 0, 0, 0.15); }
.dropdown-menu .dropdown-item-text { color: #dee2e6; }
.dropdown-menu .dropdown-header { color: #adb5bd; }
/* LIST GROUPS */
.list-group-item-action { color: #fff; }
.list-group-item-action:hover,
.list-group-item-action:focus { color: #fff; background-color: #333; }
.list-group-item-action:active { color: #212529; background-color: #e9ecef; }
.list-group-item { background-color: #111; border: 1px solid #333; }
.list-group-item:not(:first-child) { border-top: none; }
.list-group-item.disabled,
.list-group-item:disabled { color: #fff; background-color: #000; }
.list-group-item.active { color: #fff; background-color: #0d6efd; border-color: #0d6efd; }
/* TABS */
.nav-tabs { border-bottom: 1px solid #000; }
.nav-tabs .nav-link:hover,
[data-theme="dark"].nav-tabs .nav-link:focus { border-color: #212529 #212529 #000; }
.nav-tabs .nav-link.disabled { color: #333; }
.nav-tabs .nav-link.active,
.nav-tabs .nav-item.show .nav-link { color: #fff; background-color: #000; border-color: #212529 #212529 #000; }
/* PAGINATION */
.page-link { color: #fff; background-color: #111; border: 1px solid #333; }
.page-link:hover { color: #fff; background-color: #333; border-color: #333; }
.page-link:focus { color: #fff; background-color: #000; }
.page-item.active .page-link { color: #fff; background-color: #0d6efd; border-color: #0d6efd; }
.page-item.disabled .page-link { color: #fff; background-color: #000; border-color: #333; }
/* BACKGROUNDS */
.bg-light { background-color: #212529 !important; }
.bg-dark { background-color: #f8f9fa !important; }
.bg-white { background-color: #000 !important; }
.bg-white.text-white,
.bg-dark.text-white,
.bg-warning.text-dark,
.bg-info.text-dark { color: #212529 !important; }
/* BORDERS */
.border,
.border-top,
.border-end,
.border-bottom,
.border-start { border-color: rgba(66, 70, 73, 0.5) !important; }
/* BREADCRUMB */
.breadcrumb.border { border-color: #333 !important; }
/* SHADOWS */
.shadow { box-shadow: 0 0.5rem 1rem rgba(255, 255, 255, 0.15) !important; }
.shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(255, 255, 255, 0.075) !important; }
.shadow-lg { box-shadow: 0 1rem 3rem rgba(255, 255, 255, 0.175) !important; }
/* CARDS */
.card { background-color: #000; border: 1px solid rgba(255, 255, 255, 0.125); }
/* MODALS */
.modal-content { background-color: #000; border: 1px solid rgba(255, 255, 255, 0.2); }
.modal-header { border-bottom: 1px solid #212529; }
.modal-footer { border-top: 1px solid #212529; }
.modal-backdrop.show { opacity: 0.75; }
/* ACCORDIONS */
.accordion:not(.accordion-flush) { border-top: 1px solid #333; border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; }
.accordion-button { color: #fff; background-color: #000; border: 1px solid #333; border-top: none; }
.accordion-button:not(.collapsed) { color: #fff; background-color: #111; border-bottom: none; }
.accordion-button::after { filter: invert(1) grayscale(100%) brightness(200%); }
.accordion-collapse { border: 1px solid #333; }
.accordion-flush .accordion-button { border-right: 0; border-left: 0; border-radius: 0; }
.accordion-flush .accordion-collapse { border-width: 0; }
.accordion-flush .accordion-item:first-of-type .accordion-button { border-top-width: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
.accordion-flush .accordion-item:last-of-type .accordion-button.collapsed { border-bottom-width: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; }
/* PROGRESS BARS */
.progress { background-color: #333; }
/* FORMS */
.form-control::-webkit-input-placeholder,
.form-control::-moz-placeholder,
.form-control::placeholder { color: #ccc; }
.form-control-plaintext { color: #ccc; }
.form-control { color: #fff; background-color: #333; border: 1px solid #111; }
.form-select { color: #fff; border-color: #111 !important; background: #333 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23ffffff' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; border: 1px solid #111; }
.form-select:focus { border-color: #dc3545; box-shadow: 0 0 0 0.2rem #dc3545; background-color: rgba(255,0,0,0.1); }
.form-select:focus::-ms-value { color: #495057; background-color: #fff; }
.form-select option { color: #000; }
.form-select:disabled { color: #6c757d; background-color: #e9ecef; }
.form-select:-moz-focusring { text-shadow: 0 0 0 #495057; }
/* CUSTOM */
.separator {
> .mask {
&:after {
box-shadow: 0 0 10px $light;
}
}
> span {
box-shadow:0 2px 4px $light;
background: tint-color($light, 80%);
color: $dark;
}
}
.icon {
filter: invert(1);
}
mark {
background-color: #848171;
color: $light;
}
.table, .table-striped {
> tbody > tr, > thead > tr, > tfoot > tr {
td, th {
color: $light;
}
}
}
header {
.nav-item {
color: $light;
&.active, &:hover {
color: lighten($primary, 10%) !important;
}
}
}
}

View File

@ -42,6 +42,8 @@ $fa-font-path: "~@fortawesome/fontawesome-pro/webfonts";
@import "~@fortawesome/fontawesome-pro/scss/light";
@import "~@fortawesome/fontawesome-pro/scss/brands";
@import "./dark";
html {
scroll-behavior: smooth;
scroll-padding-top: 92px;

View File

@ -67,6 +67,7 @@
</li>
</ul>
<Share/>
<ModeSwitch class="mt-3"/>
</div>
</div>
</footer>

View File

@ -1,5 +1,5 @@
<template>
<img v-if="icon.endsWith('.svg')" :src="`/img/${icon}`" :style="`height: ${size}em; width: ${size}em; display: inline;`" alt=""/>
<img v-if="icon.endsWith('.svg')" :src="`/img/${icon}`" :style="`height: ${size}em; width: ${size}em; display: inline;`" alt="" class="icon"/>
<span v-else :class="['fa' + iconSet, 'fa-' + icon, 'fa-fw']" :style="`font-size: ${size}em`"></span>
</template>

36
components/ModeSwitch.vue Normal file
View File

@ -0,0 +1,36 @@
<template>
<div class="py-2 px-3">
<div class="form-check form-switch text-dark">
<label>
<input class="form-check-input" type="checkbox" v-model="isDark">
<Icon :v="isDark ? 'moon' : 'sun'"/>
</label>
</div>
</div>
</template>
<script>
import dark from "../plugins/dark";
export default {
mixins: [dark],
data() {
return {
isDark: false,
}
},
mounted() {
if (!process.client) {
return false;
}
this.isDark = this.detectDark();
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => this.isDark = e.matches);
},
watch: {
isDark(dark) {
this.setMode(dark);
}
}
}
</script>

View File

@ -17,8 +17,10 @@
<script>
import Vue from 'vue';
import dark from "../plugins/dark";
export default {
mixins: [dark],
mounted() {
Vue.prototype.$alert = (message, color='primary') => {
return new Promise((resolve, reject) => {
@ -41,6 +43,7 @@
});
});
};
this.setMode(this.detectDark());
}
}
</script>

29
plugins/dark.js Normal file
View File

@ -0,0 +1,29 @@
export default {
methods: {
detectDark() {
if (!process.client) {
return false;
}
if (localStorage.getItem('darkMode') !== null && localStorage.getItem('darkMode') === 'dark') {
return true;
}
const mediaMatch = window.matchMedia('(prefers-color-scheme: dark)');
return mediaMatch.matches;
},
setMode(dark) {
if (!process.client) {
return;
}
if (dark) {
document.body.setAttribute('data-theme', 'dark');
localStorage.setItem('darkMode', 'dark');
} else {
document.body.removeAttribute('data-theme');
localStorage.removeItem('darkMode');
}
},
}
}