mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-27 22:49:42 -08:00
FEAT: darkmode (#155)
* darkmode fixes * fix: darkmode: empty beats in active/ hovered state * fix: color for empty beats * fix: navbar background color * Update src/assets/vars.scss Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> * Update src/assets/app.scss Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> * wip, split dark theme style by .dark and store light theme to normal * add back missing css * working switch theme button and tuning dark theme * finish dark theme Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> Co-authored-by: LouisLam <louislam@users.noreply.github.com>
This commit is contained in:
parent
d5b40dfebf
commit
123fca43a1
|
@ -122,9 +122,11 @@ class Monitor extends BeanModel {
|
||||||
try {
|
try {
|
||||||
await this.updateTlsInfo(checkCertificate(res));
|
await this.updateTlsInfo(checkCertificate(res));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (e.message !== "No TLS certificate in response") {
|
||||||
console.error(e.message)
|
console.error(e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms")
|
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms")
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,26 @@
|
||||||
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;
|
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
border-radius: 1rem;
|
||||||
|
box-shadow: 0 15px 70px rgba(0, 0, 0, .1);
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
box-shadow: 0 15px 70px rgb(0 0 0);
|
||||||
|
background-color: $dark-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.VuePagination__count {
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.shadow-box {
|
.shadow-box {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 15px 70px rgba(0, 0, 0, .1);
|
box-shadow: 0 15px 70px rgba(0, 0, 0, .1);
|
||||||
|
@ -29,10 +49,87 @@
|
||||||
background-color: $highlight;
|
background-color: $highlight;
|
||||||
border-color: $highlight;
|
border-color: $highlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-font-color2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
border-radius: 1rem;
|
|
||||||
backdrop-filter: blur(3px);
|
// Dark Theme override here
|
||||||
|
.dark {
|
||||||
|
background-color: #090C10;
|
||||||
|
color: $dark-font-color;
|
||||||
|
|
||||||
|
.shadow-box {
|
||||||
|
background-color: $dark-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-check-input {
|
||||||
|
background-color: $dark-bg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-switch .form-check-input {
|
||||||
|
background-color: #131a21;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
.table,
|
||||||
|
.nav-link {
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control,
|
||||||
|
.form-control:focus,
|
||||||
|
.form-select,
|
||||||
|
.form-select:focus {
|
||||||
|
color: $dark-font-color;
|
||||||
|
background-color: $dark-bg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control, .form-select {
|
||||||
|
border-color: $dark-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-hover > tbody > tr:hover {
|
||||||
|
--bs-table-accent-bg: #070A10;
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||||
|
color: $dark-font-color2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-primary {
|
||||||
|
color: $dark-font-color2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-close {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
border-color: $dark-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
border-color: $dark-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
.page-item.disabled .page-link {
|
||||||
|
background-color: $dark-bg;
|
||||||
|
border-color: $dark-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-link {
|
||||||
|
background-color: $dark-bg;
|
||||||
|
border-color: $dark-border-color;
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,3 +6,9 @@ $border-radius: 50rem;
|
||||||
|
|
||||||
$highlight: #7ce8a4;
|
$highlight: #7ce8a4;
|
||||||
$highlight-white: #e7faec;
|
$highlight-white: #e7faec;
|
||||||
|
|
||||||
|
$dark-font-color: #b1b8c0;
|
||||||
|
$dark-font-color2: #020b05;
|
||||||
|
$dark-bg: #0D1117;
|
||||||
|
$dark-bg2: #070A10;
|
||||||
|
$dark-border-color: #1d2634;
|
||||||
|
|
|
@ -133,7 +133,7 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
@import "../assets/vars.scss";
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
.wrap {
|
.wrap {
|
||||||
|
@ -150,6 +150,10 @@ export default {
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
background-color: aliceblue;
|
background-color: aliceblue;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
background-color: #d0d3d5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.down {
|
&.down {
|
||||||
|
@ -168,4 +172,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.hp-bar-big .beat.empty{
|
||||||
|
background-color: #848484;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -325,7 +325,7 @@
|
||||||
<p>
|
<p>
|
||||||
Status:
|
Status:
|
||||||
<span v-if="appriseInstalled" class="text-primary">Apprise is installed</span>
|
<span v-if="appriseInstalled" class="text-primary">Apprise is installed</span>
|
||||||
<span v-else class="text-danger">Apprise is not installed. <a href="https://github.com/caronc/apprise">Read more</a></span>
|
<span v-else class="text-danger">Apprise is not installed. <a href="https://github.com/caronc/apprise" target="_blank">Read more</a></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -512,3 +512,13 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.modal-dialog .form-text, .modal-dialog p {
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div :class="$root.theme">
|
||||||
<div v-if="! $root.socket.connected && ! $root.socket.firstConnect" class="lost-connection">
|
<div v-if="! $root.socket.connected && ! $root.socket.firstConnect" class="lost-connection">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{ $root.connectionErrorMsg }}
|
{{ $root.connectionErrorMsg }}
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- Mobile header -->
|
<!-- Mobile header -->
|
||||||
<header v-else class="d-flex flex-wrap justify-content-center mt-3 mb-3">
|
<header v-else class="d-flex flex-wrap justify-content-center pt-2 pb-2 mb-3">
|
||||||
<router-link to="/dashboard" class="d-flex align-items-center text-dark text-decoration-none">
|
<router-link to="/dashboard" class="d-flex align-items-center text-dark text-decoration-none">
|
||||||
<object class="bi" width="40" height="40" data="/icon.svg" />
|
<object class="bi" width="40" height="40" data="/icon.svg" />
|
||||||
<span class="fs-4 title ms-2">Uptime Kuma</span>
|
<span class="fs-4 title ms-2">Uptime Kuma</span>
|
||||||
|
@ -71,6 +72,7 @@
|
||||||
Settings
|
Settings
|
||||||
</router-link>
|
</router-link>
|
||||||
</nav>
|
</nav>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -103,7 +105,7 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
@import "../assets/vars.scss";
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
.bottom-nav {
|
.bottom-nav {
|
||||||
|
@ -159,9 +161,24 @@ footer {
|
||||||
color: #AAA;
|
color: #AAA;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
header {
|
||||||
|
background-color: #161B22;
|
||||||
|
border-bottom-color: #161B22 !important;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #F0F6FC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-nav {
|
||||||
|
background-color: $dark-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { FontAwesomeIcon } from "./icon.js";
|
||||||
import EmptyLayout from "./layouts/EmptyLayout.vue";
|
import EmptyLayout from "./layouts/EmptyLayout.vue";
|
||||||
import Layout from "./layouts/Layout.vue";
|
import Layout from "./layouts/Layout.vue";
|
||||||
import socket from "./mixins/socket";
|
import socket from "./mixins/socket";
|
||||||
|
import theme from "./mixins/theme";
|
||||||
import Dashboard from "./pages/Dashboard.vue";
|
import Dashboard from "./pages/Dashboard.vue";
|
||||||
import DashboardHome from "./pages/DashboardHome.vue";
|
import DashboardHome from "./pages/DashboardHome.vue";
|
||||||
import Details from "./pages/Details.vue";
|
import Details from "./pages/Details.vue";
|
||||||
|
@ -77,6 +78,7 @@ const router = createRouter({
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
mixins: [
|
mixins: [
|
||||||
socket,
|
socket,
|
||||||
|
theme
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -29,7 +29,7 @@ export default {
|
||||||
notificationList: [],
|
notificationList: [],
|
||||||
windowWidth: window.innerWidth,
|
windowWidth: window.innerWidth,
|
||||||
showListMobile: false,
|
showListMobile: false,
|
||||||
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting..."
|
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
39
src/mixins/theme.js
Normal file
39
src/mixins/theme.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
export default {
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
system: (window.matchMedia("(prefers-color-scheme: dark)")) ? "dark" : "light",
|
||||||
|
userTheme: localStorage.theme,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
// Default Light
|
||||||
|
if (! this.userTheme) {
|
||||||
|
this.userTheme = "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.classList.add(this.theme);
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
theme() {
|
||||||
|
if (this.userTheme === "auto") {
|
||||||
|
return this.system;
|
||||||
|
}
|
||||||
|
return this.userTheme;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
userTheme(to, from) {
|
||||||
|
localStorage.theme = to;
|
||||||
|
},
|
||||||
|
|
||||||
|
theme(to, from) {
|
||||||
|
document.body.classList.remove(from);
|
||||||
|
document.body.classList.add(this.theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
@import "../assets/vars.scss";
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
|
@ -133,4 +133,18 @@ export default {
|
||||||
padding-right: 5px !important;
|
padding-right: 5px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.list {
|
||||||
|
.item {
|
||||||
|
&:hover {
|
||||||
|
background-color: $dark-bg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $dark-bg2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -169,7 +169,7 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
@import "../assets/vars";
|
@import "../assets/vars";
|
||||||
|
|
||||||
.num {
|
.num {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
|
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
|
||||||
<span v-if="monitor.type === 'keyword'">
|
<span v-if="monitor.type === 'keyword'">
|
||||||
<br>
|
<br>
|
||||||
<span>Keyword:</span> <span style="color: black">{{ monitor.keyword }}</span>
|
<span>Keyword:</span> <span class="keyword">{{ monitor.keyword }}</span>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -352,4 +352,14 @@ table {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.keyword {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.keyword {
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,6 +20,19 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
|
||||||
|
<input id="btncheck1" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="light">
|
||||||
|
<label class="btn btn-outline-primary" for="btncheck1">Light</label>
|
||||||
|
|
||||||
|
<input id="btncheck2" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="dark">
|
||||||
|
<label class="btn btn-outline-primary" for="btncheck2">Dark</label>
|
||||||
|
|
||||||
|
<input id="btncheck3" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="auto">
|
||||||
|
<label class="btn btn-outline-primary" for="btncheck3">Auto</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="btn btn-primary" type="submit">
|
<button class="btn btn-primary" type="submit">
|
||||||
Save
|
Save
|
||||||
|
@ -67,7 +80,7 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="notification-list col-md-6">
|
||||||
<div v-if="$root.isMobile" class="mt-3" />
|
<div v-if="$root.isMobile" class="mt-3" />
|
||||||
|
|
||||||
<h2>Notifications</h2>
|
<h2>Notifications</h2>
|
||||||
|
@ -201,8 +214,17 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
.shadow-box {
|
.shadow-box {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.list-group-item {
|
||||||
|
background-color: $dark-bg2;
|
||||||
|
color: $dark-font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -29,7 +29,7 @@ function ucfirst(str) {
|
||||||
exports.ucfirst = ucfirst;
|
exports.ucfirst = ucfirst;
|
||||||
function debug(msg) {
|
function debug(msg) {
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
console.log(msg);
|
console.debug(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.debug = debug;
|
exports.debug = debug;
|
||||||
|
|
|
@ -39,6 +39,6 @@ export function ucfirst(str) {
|
||||||
|
|
||||||
export function debug(msg) {
|
export function debug(msg) {
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
console.log(msg)
|
console.debug(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue