From a3d191f8182cdddcf5b32b2b32e7563c174d7f52 Mon Sep 17 00:00:00 2001 From: Jimmy Cai Date: Wed, 23 Dec 2020 17:15:17 +0100 Subject: [PATCH] feat(darkmode): initial support for dark mode toggle --- assets/scss/partials/darkmode.scss | 26 +++++++ .../partials/highlight/dark.scss} | 5 -- .../partials/highlight/light.scss} | 4 - assets/scss/partials/menu.scss | 3 +- assets/scss/style.scss | 1 + assets/scss/variables.scss | 19 ++++- assets/ts/darkmode.ts | 76 +++++++++++++++++++ assets/ts/main.ts | 3 + layouts/_default/baseof.html | 22 +++++- .../partials/footer/components/highlight.html | 4 - layouts/partials/footer/include.html | 1 - layouts/partials/sidebar/left.html | 6 ++ 12 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 assets/scss/partials/darkmode.scss rename assets/{css/highlight/dark.css => scss/partials/highlight/dark.scss} (98%) rename assets/{css/highlight/light.css => scss/partials/highlight/light.scss} (98%) create mode 100644 assets/ts/darkmode.ts delete mode 100644 layouts/partials/footer/components/highlight.html diff --git a/assets/scss/partials/darkmode.scss b/assets/scss/partials/darkmode.scss new file mode 100644 index 0000000..dc0abd8 --- /dev/null +++ b/assets/scss/partials/darkmode.scss @@ -0,0 +1,26 @@ +[data-scheme="dark"] { + #dark-mode-toggle { + color: var(--accent-color); + font-weight: 700; + + .icon-tabler-toggle-left { + display: none; + } + + .icon-tabler-toggle-right { + display: unset; + } + } +} + +#dark-mode-toggle { + margin-top: auto; + color: var(--body-text-color); + display: flex; + align-items: center; + cursor: pointer; + + .icon-tabler-toggle-right { + display: none; + } +} diff --git a/assets/css/highlight/dark.css b/assets/scss/partials/highlight/dark.scss similarity index 98% rename from assets/css/highlight/dark.css rename to assets/scss/partials/highlight/dark.scss index 7f5b872..00e8942 100644 --- a/assets/css/highlight/dark.css +++ b/assets/scss/partials/highlight/dark.scss @@ -3,11 +3,6 @@ * https://xyproto.github.io/splash/docs/monokai.html */ -:root { - --pre-text-color: #f8f8f2; - --pre-background-color: #272822; -} - /* Background */ .chroma { color: #f8f8f2; diff --git a/assets/css/highlight/light.css b/assets/scss/partials/highlight/light.scss similarity index 98% rename from assets/css/highlight/light.css rename to assets/scss/partials/highlight/light.scss index 9c4e0da..7ac7d71 100644 --- a/assets/css/highlight/light.css +++ b/assets/scss/partials/highlight/light.scss @@ -2,10 +2,6 @@ * Style: monokailight * https://xyproto.github.io/splash/docs/monokailight.html */ -:root { - --pre-text-color: #272822; - --pre-background-color: #fafafa; -} /* Background */ .chroma { diff --git a/assets/scss/partials/menu.scss b/assets/scss/partials/menu.scss index 5cefeb3..024b3a6 100644 --- a/assets/scss/partials/menu.scss +++ b/assets/scss/partials/menu.scss @@ -129,6 +129,8 @@ margin-top: var(--sidebar-element-separation); margin-bottom: 0; overflow-y: auto; + flex-grow: 1; + font-size: 1.5rem; @media (min-width: $on-desktop-large) { margin-top: 30px; @@ -192,7 +194,6 @@ display: inline-flex; align-items: center; color: var(--body-text-color); - font-size: 1.5rem; @media (max-width: $on-desktop-large) { font-size: 1.4rem; diff --git a/assets/scss/style.scss b/assets/scss/style.scss index 2f5aac9..030273a 100644 --- a/assets/scss/style.scss +++ b/assets/scss/style.scss @@ -19,6 +19,7 @@ @import "partials/pagination.scss"; @import "partials/sidebar.scss"; @import "partials/base.scss"; +@import "partials/darkmode.scss"; @import "partials/layout/archives.scss"; @import "partials/layout/article.scss"; @import "partials/layout/list.scss"; diff --git a/assets/scss/variables.scss b/assets/scss/variables.scss index 14d9e07..3a8a1a5 100644 --- a/assets/scss/variables.scss +++ b/assets/scss/variables.scss @@ -1,6 +1,18 @@ $defaultTagBackgrounds: #8ea885, #df7988, #0177b8, #ffb900, #6b69d6; $defaultTagColors: #fff, #fff, #fff, #fff, #fff; +[data-scheme="light"] { + --pre-text-color: #272822; + --pre-background-color: #fafafa; + @import "partials/highlight/light.scss"; +} + +[data-scheme="dark"] { + --pre-text-color: #f8f8f2; + --pre-background-color: #272822; + @import "partials/highlight/dark.scss"; +} + /* * Global style */ @@ -13,7 +25,6 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; --main-top-padding: 50px; } - --body-background: #f5f5fa; --accent-color: #34495e; @@ -25,7 +36,7 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; --section-separation: 40px; - @media (prefers-color-scheme: dark) { + [data-scheme="dark"] { --body-background: #303030; --accent-color: #ecf0f1; --accent-color-darker: #bdc3c7; @@ -72,7 +83,7 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; --small-card-padding: 25px 20px; } - @media (prefers-color-scheme: dark) { + [data-scheme="dark"] { --card-background: #424242; --card-background-selected: rgba(255, 255, 255, 0.16); --card-text-color-main: rgba(255, 255, 255, 0.9); @@ -116,7 +127,7 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; --table-border-color: #dadada; --tr-even-background-color: #efefee; - @media (prefers-color-scheme: dark) { + [data-scheme="dark"] { --code-background-color: #272822; --code-text-color: rgba(255, 255, 255, 0.9); diff --git a/assets/ts/darkmode.ts b/assets/ts/darkmode.ts new file mode 100644 index 0000000..828b8e2 --- /dev/null +++ b/assets/ts/darkmode.ts @@ -0,0 +1,76 @@ +type colorScheme = 'light' | 'dark' | 'auto'; + +class StackDarkMode { + private localStorageKey = 'StackColorScheme'; + private currentScheme: colorScheme; + private systemPreferScheme: colorScheme; + + constructor(toggleEl: HTMLElement) { + this.bindMatchMedia(); + this.currentScheme = this.getSavedScheme(); + this.setBodyClass(); + this.bindClick(toggleEl); + } + + private saveScheme() { + localStorage.setItem(this.localStorageKey, this.currentScheme); + } + + private bindClick(toggleEl) { + toggleEl.addEventListener('click', (e) => { + if (this.isDark()) { + /// Disable dark mode + this.currentScheme = 'light'; + } + else { + this.currentScheme = 'dark'; + } + + this.setBodyClass(); + + if (this.currentScheme == this.systemPreferScheme) { + /// Set to auto + this.currentScheme = 'auto'; + } + + this.saveScheme(); + }) + } + + private isDark() { + return (this.currentScheme == 'dark' || this.currentScheme == 'auto' && this.preferDarkMode); + } + + private setBodyClass() { + if (document.body.style.transition == '') + document.body.style.setProperty('transition', 'background-color .3s ease'); + + if (this.isDark()) { + document.body.dataset.scheme = 'dark'; + } + else { + document.body.dataset.scheme = 'light'; + } + } + + private getSavedScheme(): colorScheme { + const savedScheme = localStorage.getItem(this.localStorageKey); + + if (savedScheme == 'light' || savedScheme == 'dark' || savedScheme == 'auto') return savedScheme; + else return 'auto'; + } + + private bindMatchMedia() { + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { + if (e.matches) { + this.systemPreferScheme = 'dark'; + } + else { + this.systemPreferScheme = 'light'; + } + this.setBodyClass(); + }); + } +} + +export default StackDarkMode; \ No newline at end of file diff --git a/assets/ts/main.ts b/assets/ts/main.ts index 4d07631..e1b9db9 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -9,6 +9,7 @@ import StackGallery from "ts/gallery"; import { getColor } from 'ts/color'; import menu from 'ts/menu'; import createElement from 'ts/createElement'; +import StackDarkMode from 'ts/darkmode'; let Stack = { init: () => { @@ -52,6 +53,8 @@ let Stack = { observer.observe(articleTile) } + + new StackDarkMode(document.getElementById('dark-mode-toggle')); } } diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 06a31e5..68f1974 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -5,7 +5,27 @@ {{- block "head" . -}}{{ end }} -
+ + +
{{ partial "sidebar/left.html" . }}
{{- block "main" . }}{{- end }} diff --git a/layouts/partials/footer/components/highlight.html b/layouts/partials/footer/components/highlight.html deleted file mode 100644 index 80ec266..0000000 --- a/layouts/partials/footer/components/highlight.html +++ /dev/null @@ -1,4 +0,0 @@ -{{- $light := resources.Get "css/highlight/light.css" | minify -}} -{{- $dark := resources.Get "css/highlight/dark.css" | minify -}} - - \ No newline at end of file diff --git a/layouts/partials/footer/include.html b/layouts/partials/footer/include.html index ffa7573..4b50a88 100644 --- a/layouts/partials/footer/include.html +++ b/layouts/partials/footer/include.html @@ -1,4 +1,3 @@ {{ partialCached "footer/components/script.html" . }} {{ partialCached "footer/components/custom-font.html" . }} -{{ partialCached "footer/components/highlight.html" . }} {{ partial "footer/custom.html" . }} \ No newline at end of file diff --git a/layouts/partials/sidebar/left.html b/layouts/partials/sidebar/left.html index 9205fa4..dba76f2 100644 --- a/layouts/partials/sidebar/left.html +++ b/layouts/partials/sidebar/left.html @@ -45,5 +45,11 @@ {{ end }} + +
  • + {{ partial "helper/icon" "toggle-left" }} + {{ partial "helper/icon" "toggle-right" }} + Dark Mode +