From 817845a70bbcbf82ed744ba4585a6d7a176abd2a Mon Sep 17 00:00:00 2001 From: Dominik Pschenitschni Date: Fri, 12 Nov 2021 14:34:36 +0100 Subject: [PATCH] feat: add color scheme setting --- package.json | 1 + src/App.vue | 4 ++ src/composables/useColorScheme.ts | 48 +++++++++++++++++++++++ src/i18n/lang/en.json | 9 +++++ src/styles/custom-properties/colors.scss | 2 +- src/styles/custom-properties/shadows.scss | 2 +- src/views/user/settings/General.vue | 48 +++++++++++++++++++++++ yarn.lock | 20 ++++++++++ 8 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/composables/useColorScheme.ts diff --git a/package.json b/package.json index dcaae92e0..97b4a83f5 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@sentry/tracing": "6.14.1", "@sentry/vue": "6.14.1", "@vue/compat": "3.2.21", + "@vueuse/core": "^6.8.0", "bulma-css-variables": "^0.9.33", "camel-case": "4.1.2", "codemirror": "5.63.3", diff --git a/src/App.vue b/src/App.vue index 5138a8b91..d93901a10 100644 --- a/src/App.vue +++ b/src/App.vue @@ -36,6 +36,7 @@ import ContentLinkShare from './components/home/contentLinkShare' import ContentNoAuth from './components/home/contentNoAuth' import {setLanguage} from './i18n' import AccountDeleteService from '@/services/accountDelete' +import {useColorScheme} from '@/composables/useColorScheme' export default defineComponent({ name: 'app', @@ -63,6 +64,9 @@ export default defineComponent({ setLanguage() }, + setup() { + useColorScheme() + }, created() { // Make sure to always load the home route when running with electron if (this.$route.fullPath.endsWith('frontend/index.html')) { diff --git a/src/composables/useColorScheme.ts b/src/composables/useColorScheme.ts new file mode 100644 index 000000000..f4bf2b257 --- /dev/null +++ b/src/composables/useColorScheme.ts @@ -0,0 +1,48 @@ +import {computed, watch, readonly} from 'vue' +import {useStorage, createSharedComposable, ColorSchemes, usePreferredColorScheme, tryOnMounted} from '@vueuse/core' + +const STORAGE_KEY = 'color-scheme' + +const DEFAULT_COLOR_SCHEME_SETTING: ColorSchemes = 'light' + +const CLASS_DARK = 'dark' +const CLASS_LIGHT = 'light' + +// This is built upon the vueuse useDark +// Main differences: +// - usePreferredColorScheme +// - doesn't allow setting via the `isDark` ref. +// - instead the store is exposed +// - value is synced via `createSharedComposable` +// https://github.com/vueuse/vueuse/blob/main/packages/core/useDark/index.ts +export const useColorScheme = createSharedComposable(() => { + const store = useStorage(STORAGE_KEY, DEFAULT_COLOR_SCHEME_SETTING) + + const preferredColorScheme = usePreferredColorScheme() + + const isDark = computed(() => { + if (store.value !== 'auto') { + return store.value === 'dark' + } + + const autoColorScheme = preferredColorScheme.value === 'no-preference' + ? DEFAULT_COLOR_SCHEME_SETTING + : preferredColorScheme.value + return autoColorScheme === 'dark' + }) + + function onChanged(v: boolean) { + const el = window?.document.querySelector('html') + el?.classList.toggle(CLASS_DARK, v) + el?.classList.toggle(CLASS_LIGHT, !v) + } + + watch(isDark, onChanged, { flush: 'post' }) + + tryOnMounted(() => onChanged(isDark.value)) + + return { + store, + isDark: readonly(isDark), + } +}) \ No newline at end of file diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json index e8fd95bd1..653fed56f 100644 --- a/src/i18n/lang/en.json +++ b/src/i18n/lang/en.json @@ -102,6 +102,15 @@ "disabled": "Disabled", "todoist": "Todoist", "vikunja": "Vikunja" + }, + "appearance": { + "title": "Color Scheme", + "setSuccess": "Saved change of color scheme to {colorScheme}", + "colorScheme": { + "light": "Light", + "system": "System", + "dark": "Dark" + } } }, "deletion": { diff --git a/src/styles/custom-properties/colors.scss b/src/styles/custom-properties/colors.scss index cb601d6d6..8cba8dbb1 100644 --- a/src/styles/custom-properties/colors.scss +++ b/src/styles/custom-properties/colors.scss @@ -81,7 +81,7 @@ --card-border-color: var(--grey-200); - @media (prefers-color-scheme: dark) { + &.dark { // Light mode colours reversed for dark mode --grey-900-hsl: 210, 20%, 98%; --grey-900: hsl(var(--grey-900-hsl)); diff --git a/src/styles/custom-properties/shadows.scss b/src/styles/custom-properties/shadows.scss index 97275dfde..bbeb34fa7 100644 --- a/src/styles/custom-properties/shadows.scss +++ b/src/styles/custom-properties/shadows.scss @@ -8,7 +8,7 @@ --shadow-lg: 0 15px 25px hsla(var(--grey-500-hsl), .12), 0 5px 10px hsla(var(--grey-500-hsl), .05); - @media (prefers-color-scheme: dark) { + &.dark { // Even darker shadows for dark mode --shadow-xs: 0 1px 3px hsla(var(--grey-100-hsl),.12), 0 1px 2px hsla(var(--grey-100-hsl), .24); diff --git a/src/views/user/settings/General.vue b/src/views/user/settings/General.vue index db3205429..347d1cc2a 100644 --- a/src/views/user/settings/General.vue +++ b/src/views/user/settings/General.vue @@ -90,6 +90,21 @@ +
+ +