From 077755dd2aef854a658cb05733407c5d7c125701 Mon Sep 17 00:00:00 2001 From: cgjgh <160297365+cgjgh@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:51:20 -0600 Subject: [PATCH 1/8] Add dark mode NodeRED editor config --- nodes/config/ui_base.html | 45 ++++++- nodes/config/ui_theme.html | 265 ++++++++++++++++++++++++++++--------- nodes/config/ui_theme.js | 28 +++- 3 files changed, 270 insertions(+), 68 deletions(-) diff --git a/nodes/config/ui_base.html b/nodes/config/ui_base.html index fbb039a05..bfba376af 100644 --- a/nodes/config/ui_base.html +++ b/nodes/config/ui_base.html @@ -1895,14 +1895,47 @@ $('', { class: 'nrdb2-sb-title' }).text(theme.name || theme.id).appendTo(titleRow) $('', { class: 'nrdb2-sb-info' }).text(theme.users.length + ' ' + (theme.users.length > 1 ? c_('label.pages') : c_('label.page'))).appendTo(titleRow) - const palette = $('
', { class: 'nrdb2-sb-palette' }).appendTo(titleRow) + // backward compatibility + if (!hasProperty(theme.colors, 'light') && hasProperty(theme.colors, 'surface')) { + // Set default values for light theme + const updatedColors = { + light: { + surface: theme.colors.surface, + primary: theme.colors.primary, + bgPage: theme.colors.bgPage, + groupBg: theme.colors.groupBg, + groupOutline: theme.colors.groupOutline + }, + + // Set default values for dark theme + dark: { + surface: '#111111', + primary: theme.colors.primary, + bgPage: '#222222', + groupBg: '#333333', + groupOutline: '#cccccc' + } + } + + theme.colors = updatedColors + } + + const paletteLight = $('
', { class: 'nrdb2-sb-palette' }).appendTo(titleRow) const colors = theme.colors - palette.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.surface}` })) - palette.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.primary}` })) - palette.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.bgPage}` })) - palette.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.groupBg}` })) - palette.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.groupOutline}` })) + paletteLight.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.light.surface}` })) + paletteLight.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.light.primary}` })) + paletteLight.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.light.bgPage}` })) + paletteLight.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.light.groupBg}` })) + paletteLight.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.light.groupOutline}` })) + + const paletteDark = $('
', { class: 'nrdb2-sb-palette' }).appendTo(titleRow) + + paletteDark.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.dark.surface}` })) + paletteDark.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.dark.primary}` })) + paletteDark.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.dark.bgPage}` })) + paletteDark.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.dark.groupBg}` })) + paletteDark.append($('
', { class: 'nrdb2-sb-palette-color', style: `background-color: ${colors.dark.groupOutline}` })) // theme - actions const actions = $('
', { class: 'nrdb2-sb-list-header-actions' }).appendTo(titleRow) diff --git a/nodes/config/ui_theme.html b/nodes/config/ui_theme.html index f7a38654a..412f0fb80 100644 --- a/nodes/config/ui_theme.html +++ b/nodes/config/ui_theme.html @@ -6,16 +6,30 @@ value: RED._('@flowfuse/node-red-dashboard/ui-theme:ui-theme.label.themeName'), required: true }, + // colors colors: { value: { - surface: '#ffffff', - primary: '#0094CE', - bgPage: '#eeeeee', - groupBg: '#ffffff', - groupOutline: '#cccccc' + // light mode + light: { + surface: '#ffffff', + primary: '#0094CE', + bgPage: '#eeeeee', + groupBg: '#ffffff', + groupOutline: '#cccccc' + }, + + // dark mode + dark: { + surface: '#111111', + primary: '#0094CE', + bgPage: '#222222', + groupBg: '#333333', + groupOutline: '#cccccc' + } } }, + // sizes sizes: { value: { @@ -33,15 +47,44 @@ } if (!this.colors) { - this.colors = {} - // set default values - this.colors.surface = '#ffffff' - this.colors.primary = '#0094CE' - // pages - this.colors.bgPage = '#eeeeee' - // groups - this.colors.groupBg = '#ffffff' - this.colors.groupOutline = '#cccccc' + this.colors = { + light: { + surface: '#ffffff', + primary: '#0094CE', + bgPage: '#eeeeee', + groupBg: '#ffffff', + groupOutline: '#cccccc' + }, + dark: { + surface: '#111111', + primary: '#0094CE', + bgPage: '#222222', + groupBg: '#333333', + groupOutline: '#cccccc' + } + } + } else if (!hasProperty(this.colors, 'light') && hasProperty(this.colors, 'surface')) { + // Set default values for light theme + const updatedColors = { + light: { + surface: this.colors.surface, + primary: this.colors.primary, + bgPage: this.colors.bgPage, + groupBg: this.colors.groupBg, + groupOutline: this.colors.groupOutline + }, + + // Set default values for dark theme + dark: { + surface: '#111111', + primary: this.colors.primary, + bgPage: '#222222', + groupBg: '#333333', + groupOutline: '#cccccc' + } + } + + this.colors = updatedColors } if (!this.sizes) { @@ -65,11 +108,12 @@ } // loop over keys in this.colors - Object.keys(this.colors).forEach((color) => { - // get the value of the key - const value = this.colors[color] - // set the value of the input - $('#node-config-input-' + color).val(value) + Object.keys(this.colors).forEach((theme) => { + const colors = this.colors[theme] + Object.keys(colors).forEach((color) => { + const value = colors[color] + $('#node-config-input-' + theme + '-' + color).val(value) + }) }) // loop over keys in this.sizes @@ -93,12 +137,36 @@ }) wrapper.css('background-color', colorPicker.val()) }) + + const that = this + const tabs = RED.tabs.create({ + id: 'color-tabs', + onchange: function (tab) { + $('#color-tabs-content').children().hide() + $('#' + tab.id).show() + } + }) + tabs.addTab({ + id: 'color-tab-light', + iconClass: 'fa fa-sun-o', + label: that._('ui-theme.label.colorsLight') + }) + + tabs.addTab({ + id: 'color-tab-dark', + iconClass: 'fa fa-moon-o', + label: that._('ui-theme.label.colorsDark') + }) + + tabs.activateTab('color-tab-light') }, oneditsave: function () { // update our config values from the input values - Object.keys(this.colors).forEach((color) => { - // set the value of the input - this.colors[color] = $('#node-config-input-' + color).val() + Object.keys(this.colors).forEach((theme) => { + const colors = this.colors[theme] + Object.keys(colors).forEach((color) => { + this.colors[theme][color] = $('#node-config-input-' + theme + '-' + color).val() + }) }) // update our config values from the input values @@ -124,49 +192,124 @@

-
-

-
-
-
- - -
-
- - -
-
-
-

-
-
- - -
-
-

+ + +
+
    -
    -
    - - +
    + -
    - - + +
    +

    diff --git a/nodes/config/ui_theme.js b/nodes/config/ui_theme.js index daaefbba1..e96c5021c 100644 --- a/nodes/config/ui_theme.js +++ b/nodes/config/ui_theme.js @@ -32,7 +32,33 @@ module.exports = function (RED) { sizes.widgetGap = '12px' } - node.colors = { ...rest.colors } + const colors = { ...rest.colors } + node.colors = colors + + if (!hasProperty(colors, 'light') && hasProperty(colors, 'surface')) { + // Set default values for light theme + const updatedColors = { + light: { + surface: colors.surface, + primary: colors.primary, + bgPage: colors.bgPage, + groupBg: colors.groupBg, + groupOutline: colors.groupOutline + }, + + // Set default values for dark theme + dark: { + surface: '#111111', + primary: colors.primary, + bgPage: '#222222', + groupBg: '#333333', + groupOutline: '#cccccc' + } + } + + node.colors = updatedColors + } + node.sizes = sizes let uiBase = null From 0c21ecc61ff1ad15f5d49c7517f9ce0d9fae9130 Mon Sep 17 00:00:00 2001 From: cgjgh <160297365+cgjgh@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:49:39 -0600 Subject: [PATCH 2/8] Add darkMode to store --- ui/src/store/ui.mjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ui/src/store/ui.mjs b/ui/src/store/ui.mjs index 0a08b0c11..eddaa03bc 100644 --- a/ui/src/store/ui.mjs +++ b/ui/src/store/ui.mjs @@ -4,7 +4,8 @@ const state = () => ({ pages: null, groups: null, themes: null, - widgets: null + widgets: null, + darkMode: JSON.parse(localStorage.getItem('ndrb-theme-dark-mode')) || false }) // getters @@ -30,6 +31,11 @@ const getters = { widgets (state) { return state.widgets }, + + darkMode (state) { + return state.darkMode + }, + pageByName: (state) => (name) => { if (state.pages) { return Object.values(state.pages).filter((p) => { @@ -184,6 +190,9 @@ const mutations = { for (const prop in config) { state[item + 's'][itemId][prop] = config[prop] } + }, + setDarkMode (state, darkMode) { + state.darkMode = darkMode } } From db4718c0e360c6ba2843bf32ef3a88f296251a82 Mon Sep 17 00:00:00 2001 From: cgjgh <160297365+cgjgh@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:50:20 -0600 Subject: [PATCH 3/8] Setup initial dark and light themes --- ui/src/main.mjs | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/ui/src/main.mjs b/ui/src/main.mjs index 9a5b4bf47..b963828cf 100644 --- a/ui/src/main.mjs +++ b/ui/src/main.mjs @@ -35,21 +35,48 @@ function retrieveDefaultThemeFromCache () { return null } +function retrieveDarkModeFromCache () { + const cachedDarkMode = localStorage.getItem('ndrb-theme-dark-mode') + if (cachedDarkMode) { + return JSON.parse(cachedDarkMode) + } + return false +} + const defaultTheme = retrieveDefaultThemeFromCache() +const darkMode = retrieveDarkModeFromCache() // set a base theme on which we will add our custom NR-defined theme (initially set to the default theme if exists in cache) -const theme = { +const lightTheme = { dark: false, colors: { - background: defaultTheme ? defaultTheme.colors.bgPage : '#fff', - 'navigation-background': defaultTheme ? defaultTheme.colors.surface : '#ffffff', - 'group-background': defaultTheme ? defaultTheme.colors.groupBg : '#ffffff', - 'group-outline': defaultTheme ? defaultTheme.colors.groupOutline : '#d1d1d1', - primary: defaultTheme ? defaultTheme.colors.primary : '#0094CE', + background: defaultTheme ? defaultTheme.colors.light.bgPage : '#fff', + 'navigation-background': defaultTheme ? defaultTheme.colors.light.surface : '#ffffff', + 'group-background': defaultTheme ? defaultTheme.colors.light.groupBg : '#ffffff', + 'group-outline': defaultTheme ? defaultTheme.colors.light.groupOutline : '#d1d1d1', + primary: defaultTheme ? defaultTheme.colors.light.primary : '#0094CE', + accent: '#ff6b99', + secondary: '#26ff8c', + success: '#a5d64c', + surface: defaultTheme ? defaultTheme.colors.light.surface : '#ffffff', + info: '#ff53d0', + warning: '#ff8e00', + error: '#ff5252' + } +} + +const darkTheme = { + dark: true, + colors: { + background: defaultTheme ? defaultTheme.colors.dark.bgPage : '#222222', + 'navigation-background': defaultTheme ? defaultTheme.colors.dark.surface : '#111111', + 'group-background': defaultTheme ? defaultTheme.colors.dark.groupBg : '#333333', + 'group-outline': defaultTheme ? defaultTheme.colors.dark.groupOutline : '#cccccc', + primary: defaultTheme ? defaultTheme.colors.dark.primary : '#0094CE', accent: '#ff6b99', secondary: '#26ff8c', success: '#a5d64c', - surface: defaultTheme ? defaultTheme.colors.surface : '#ffffff', + surface: defaultTheme ? defaultTheme.colors.dark.surface : '#111111', info: '#ff53d0', warning: '#ff8e00', error: '#ff5252' @@ -67,9 +94,10 @@ const vuetify = createVuetify({ resize: Resize }, theme: { - defaultTheme: 'nrdb', + defaultTheme: darkMode ? 'nrdbDark' : 'nrdbLight', themes: { - nrdb: theme + nrdbLight: lightTheme, + nrdbDark: darkTheme } }, defaults: { From 1dc2abf42ac0d4ad5d520c9133d3b44a2b7767a2 Mon Sep 17 00:00:00 2001 From: cgjgh <160297365+cgjgh@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:54:44 -0600 Subject: [PATCH 4/8] Add dark mode theme to Baseline --- ui/src/layouts/Baseline.vue | 58 ++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/ui/src/layouts/Baseline.vue b/ui/src/layouts/Baseline.vue index 6d0a17879..599599912 100644 --- a/ui/src/layouts/Baseline.vue +++ b/ui/src/layouts/Baseline.vue @@ -66,14 +66,34 @@ - + + \ No newline at end of file