From: Adam Dullage Date: Wed, 12 Apr 2023 06:46:09 +0000 (+0100) Subject: Dark Theme X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=d7fd912d72cf68053065cc60886f2b50969c23e7;p=flatnotes.git Dark Theme --- diff --git a/flatnotes/src/assets/logo-part-icon.svg b/flatnotes/src/assets/logo-part-icon.svg deleted file mode 100644 index 0a76642..0000000 --- a/flatnotes/src/assets/logo-part-icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/flatnotes/src/assets/logo-part-name.svg b/flatnotes/src/assets/logo-part-name.svg deleted file mode 100644 index e25db40..0000000 --- a/flatnotes/src/assets/logo-part-name.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/flatnotes/src/colours.scss b/flatnotes/src/colours.scss index ae96a09..3ddcf2c 100644 --- a/flatnotes/src/colours.scss +++ b/flatnotes/src/colours.scss @@ -1,9 +1,47 @@ -$off-white: #f8f9fd70; -$form-control-border: #ced4da; -$drop-shadow: #0000000a; -$muted-text: #6c757d; -$very-muted-text: #d8dbdd; -$text: #222222; -$button-background: #6ca7ff15; -$input-highlight: #6ca7ff; -$logo-key-colour: #f9a76b; +$black: #000000; +$white: #ffffff; + +$neutral-15: #22262C; +$neutral-20: #2C3139; +$neutral-45: #5E6B80; +$neutral-60: #8891A1; +$neutral-80: #C1C7D0; +$neutral-94: #ECEEF0; +$neutral-96: #F3F4F5; +$neutral-99: #FCFCFD; + +$blue-96: #EFF3FF; + +$orange-75: #F8A66B; + +body { + --colour-brand: #{$orange-75}; + + --colour-background: #{$neutral-99}; + --colour-background-elevated: #{$white}; + --colour-background-tint: #{$neutral-96}; + --colour-background-highlight: #{$blue-96}; + + --colour-text: #{$neutral-20}; + --colour-text-muted: #{$neutral-60}; + --colour-text-very-muted: #{$neutral-80}; + + --colour-shadow: #{$neutral-94}; + --colour-border: #{$neutral-94}; +} + +body.dark-theme { + // --colour-brand: #{$orange-75}; + + --colour-background: #{$neutral-15}; + --colour-background-elevated: #{$neutral-20}; + --colour-background-tint: #{$neutral-15}; + --colour-background-highlight: #{$neutral-60}; + + --colour-text: #{$neutral-80}; + --colour-text-muted: #{$neutral-60}; + --colour-text-very-muted: #{$neutral-45}; + + --colour-shadow: none; + --colour-border: #{$neutral-45}; +} diff --git a/flatnotes/src/components/App.js b/flatnotes/src/components/App.js index ececa96..55d5647 100644 --- a/flatnotes/src/components/App.js +++ b/flatnotes/src/components/App.js @@ -27,7 +27,7 @@ export default { RecentlyModified, }, - data: function() { + data: function () { return { authType: null, @@ -41,25 +41,36 @@ export default { noteTitle: null, searchTerm: null, + darkTheme: false, }; }, + watch: { + darkTheme: function () { + if (this.darkTheme) { + document.body.classList.add("dark-theme"); + } else { + document.body.classList.remove("dark-theme"); + } + }, + }, + methods: { - loadConfig: function() { + loadConfig: function () { let parent = this; api .get("/api/config") - .then(function(response) { + .then(function (response) { parent.authType = response.data.authType; }) - .catch(function(error) { + .catch(function (error) { if (!error.handled) { parent.unhandledServerErrorToast(); } }); }, - route: function() { + route: function () { let path = window.location.pathname.split("/"); let basePath = `/${path[1]}`; @@ -69,7 +80,7 @@ export default { if (basePath == constants.basePaths.home) { this.updateDocumentTitle(); this.currentView = this.views.home; - this.$nextTick(function() { + this.$nextTick(function () { this.focusSearchInput(); }); } @@ -101,7 +112,7 @@ export default { } }, - navigate: function(href, e) { + navigate: function (href, e) { if (e != undefined && e.ctrlKey == true) { window.open(href); } else { @@ -112,17 +123,17 @@ export default { } }, - updateDocumentTitle: function(suffix) { + updateDocumentTitle: function (suffix) { window.document.title = (suffix ? `${suffix} - ` : "") + "flatnotes"; }, - logout: function() { + logout: function () { sessionStorage.removeItem("token"); localStorage.removeItem("token"); this.navigate(constants.basePaths.login); }, - noteDeletedToast: function() { + noteDeletedToast: function () { this.$bvToast.toast("Note deleted ✓", { variant: "success", noCloseButton: true, @@ -130,13 +141,13 @@ export default { }); }, - focusSearchInput: function() { + focusSearchInput: function () { let input = document.getElementById("search-input"); input.focus(); input.select(); }, - openSearch: function() { + openSearch: function () { if ([this.views.home, this.views.search].includes(this.currentView)) { this.focusSearchInput(); EventBus.$emit("highlight-search-input"); @@ -145,7 +156,7 @@ export default { } }, - unhandledServerErrorToast: function() { + unhandledServerErrorToast: function () { this.$bvToast.toast( "Unknown error communicating with the server. Please try again.", { @@ -156,9 +167,14 @@ export default { } ); }, + + toggleTheme: function () { + this.darkTheme = !this.darkTheme; + localStorage.setItem("darkTheme", this.darkTheme); + }, }, - created: function() { + created: function () { let parent = this; this.constants = constants; @@ -167,7 +183,7 @@ export default { EventBus.$on("unhandledServerError", this.unhandledServerErrorToast); EventBus.$on("updateDocumentTitle", this.updateDocumentTitle); - Mousetrap.bind("/", function() { + Mousetrap.bind("/", function () { parent.openSearch(); return false; }); @@ -179,15 +195,25 @@ export default { sessionStorage.setItem("token", token); } + let darkTheme = localStorage.getItem("darkTheme"); + if (darkTheme != null) { + this.darkTheme = darkTheme == "true"; + } else if ( + window.matchMedia && + window.matchMedia("(prefers-color-scheme: dark)").matches + ) { + this.darkTheme = true; + } + this.route(); }, - mounted: function() { + mounted: function () { let parent = this; window.addEventListener("popstate", this.route); - this.$root.$on("bv::modal::shown", function(_, modalId) { + this.$root.$on("bv::modal::shown", function (_, modalId) { if (modalId == "search-modal") { parent.focusSearchInput(); } diff --git a/flatnotes/src/components/App.vue b/flatnotes/src/components/App.vue index f821609..33729e4 100644 --- a/flatnotes/src/components/App.vue +++ b/flatnotes/src/components/App.vue @@ -13,7 +13,9 @@ class="w-100 mb-5" :show-logo="currentView != views.home" :show-log-out="authType != null && authType != constants.authTypes.none" + :dark-theme="darkTheme" @logout="logout()" + @toggleTheme="toggleTheme()" @search="openSearch()" > @@ -82,7 +84,7 @@ } .search-input { - box-shadow: 0 0 20px $drop-shadow; + box-shadow: 0 0 20px var(--colour-shadow); } .recently-modified { diff --git a/flatnotes/src/components/LoadingIndicator.vue b/flatnotes/src/components/LoadingIndicator.vue index fc8b11d..6e2d043 100644 --- a/flatnotes/src/components/LoadingIndicator.vue +++ b/flatnotes/src/components/LoadingIndicator.vue @@ -18,11 +18,11 @@ @import "../colours"; p { - color: $muted-text; + color: var(--colour-text-muted); } .failed-icon { - color: $logo-key-colour; + color: var(--colour-brand); font-size: 60px; } @@ -34,14 +34,14 @@ p { .loader, .loader:before, .loader:after { - background: $logo-key-colour; + background: var(--colour-brand); -webkit-animation: load1 1s infinite ease-in-out; animation: load1 1s infinite ease-in-out; width: 1em; height: 4em; } .loader { - color: $logo-key-colour; + color: var(--colour-brand); text-indent: -9999em; margin: 33% auto; position: relative; diff --git a/flatnotes/src/components/Logo.vue b/flatnotes/src/components/Logo.vue index fa27e3b..1d0ebf3 100644 --- a/flatnotes/src/components/Logo.vue +++ b/flatnotes/src/components/Logo.vue @@ -1,19 +1,52 @@