Add support for custom light color palette (#2156)

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Chenlei Hu
2025-01-04 18:53:47 -05:00
committed by GitHub
parent e46706777c
commit e65653c107
10 changed files with 70 additions and 29 deletions

View File

@@ -1,8 +1,9 @@
import { expect } from '@playwright/test'
import type { Palette } from '../src/types/colorPaletteTypes'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
const customColorPalettes = {
const customColorPalettes: Record<string, Palette> = {
obsidian: {
version: 102,
id: 'obsidian',
@@ -128,6 +129,19 @@ const customColorPalettes = {
'tr-odd-bg-color': 'rgba(19,19,19,.9)'
}
}
},
// A custom light theme with fg color red
light_red: {
id: 'light_red',
name: 'Light Red',
light_theme: true,
colors: {
node_slot: {},
litegraph_base: {},
comfy_base: {
'fg-color': '#ff0000'
}
}
}
}
@@ -142,6 +156,12 @@ test.describe('Color Palette', () => {
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-obsidian-dark.png'
)
await comfyPage.setSetting('Comfy.ColorPalette', 'light_red')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-light-red.png'
)
await comfyPage.setSetting('Comfy.ColorPalette', 'dark')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('default-color-palette.png')

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -1,6 +1,7 @@
{
"id": "light",
"name": "Light",
"light_theme": true,
"colors": {
"node_slot": {
"CLIP": "#FFA726",
@@ -13,7 +14,12 @@
"MASK": "#9CCC65",
"MODEL": "#7E57C2",
"STYLE_MODEL": "#D4E157",
"VAE": "#FF7043"
"VAE": "#FF7043",
"NOISE": "#B0B0B0",
"GUIDER": "#66FFFF",
"SAMPLER": "#ECB4B4",
"SIGMAS": "#CDFFCD",
"TAESD": "#DCC274"
},
"litegraph_base": {
"BACKGROUND_IMAGE": "data:image/gif;base64,R0lGODlhZABkALMAAAAAAP///+vr6+rq6ujo6Ofn5+bm5uXl5d3d3f///wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAABkAGQAAAT/UMhJq7046827HkcoHkYxjgZhnGG6si5LqnIM0/fL4qwwIMAg0CAsEovBIxKhRDaNy2GUOX0KfVFrssrNdpdaqTeKBX+dZ+jYvEaTf+y4W66mC8PUdrE879f9d2mBeoNLfH+IhYBbhIx2jkiHiomQlGKPl4uZe3CaeZifnnijgkESBqipqqusra6vsLGys62SlZO4t7qbuby7CLa+wqGWxL3Gv3jByMOkjc2lw8vOoNSi0czAncXW3Njdx9Pf48/Z4Kbbx+fQ5evZ4u3k1fKR6cn03vHlp7T9/v8A/8Gbp4+gwXoFryXMB2qgwoMMHyKEqA5fxX322FG8tzBcRnMW/zlulPbRncmQGidKjMjyYsOSKEF2FBlJQMCbOHP6c9iSZs+UnGYCdbnSo1CZI5F64kn0p1KnTH02nSoV3dGTV7FFHVqVq1dtWcMmVQZTbNGu72zqXMuW7danVL+6e4t1bEy6MeueBYLXrNO5Ze36jQtWsOG97wIj1vt3St/DjTEORss4nNq2mDP3e7w4r1bFkSET5hy6s2TRlD2/mSxXtSHQhCunXo26NevCpmvD/UU6tuullzULH76q92zdZG/Ltv1a+W+osI/nRmyc+fRi1Xdbh+68+0vv10dH3+77KD/i6IdnX669/frn5Zsjh4/2PXju8+8bzc9/6fj27LFnX11/+IUnXWl7BJfegm79FyB9JOl3oHgSklefgxAC+FmFGpqHIYcCfkhgfCohSKKJVo044YUMttggiBkmp6KFXw1oII24oYhjiDByaKOOHcp3Y5BD/njikSkO+eBREQAAOw==",

View File

@@ -11,14 +11,15 @@
import { computed } from 'vue'
import { useCommandStore } from '@/stores/commandStore'
import { useSettingStore } from '@/stores/settingStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import SidebarIcon from './SidebarIcon.vue'
const settingStore = useSettingStore()
const currentTheme = computed(() => settingStore.get('Comfy.ColorPalette'))
const colorPaletteStore = useColorPaletteStore()
const icon = computed(() =>
currentTheme.value !== 'light' ? 'pi pi-moon' : 'pi pi-sun'
colorPaletteStore.completedActivePalette.light_theme
? 'pi pi-sun'
: 'pi pi-moon'
)
const commandStore = useCommandStore()

View File

@@ -4,7 +4,7 @@ import github from '@/assets/palettes/github.json'
import light from '@/assets/palettes/light.json'
import nord from '@/assets/palettes/nord.json'
import solarized from '@/assets/palettes/solarized.json'
import type { ColorPalettes } from '@/types/colorPaletteTypes'
import type { ColorPalettes, CompletedPalette } from '@/types/colorPaletteTypes'
export const CORE_COLOR_PALETTES: ColorPalettes = {
dark,
@@ -15,4 +15,6 @@ export const CORE_COLOR_PALETTES: ColorPalettes = {
github
} as const
export const DEFAULT_COLOR_PALETTE = dark
export const DEFAULT_COLOR_PALETTE: CompletedPalette = dark
export const DEFAULT_DARK_COLOR_PALETTE: CompletedPalette = dark
export const DEFAULT_LIGHT_COLOR_PALETTE: CompletedPalette = light

View File

@@ -5,6 +5,10 @@ import {
LiteGraph
} from '@comfyorg/litegraph'
import {
DEFAULT_DARK_COLOR_PALETTE,
DEFAULT_LIGHT_COLOR_PALETTE
} from '@/constants/coreColorPalettes'
import { api } from '@/scripts/api'
import { app } from '@/scripts/app'
import { useDialogService } from '@/services/dialogService'
@@ -16,6 +20,7 @@ import { useSettingStore } from '@/stores/settingStore'
import { useToastStore } from '@/stores/toastStore'
import { type ComfyWorkflow, useWorkflowStore } from '@/stores/workflowStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
@@ -23,6 +28,7 @@ export function useCoreCommands(): ComfyCommand[] {
const workflowService = useWorkflowService()
const workflowStore = useWorkflowStore()
const dialogService = useDialogService()
const colorPaletteStore = useColorPaletteStore()
const getTracker = () => workflowStore.activeWorkflow?.changeTracker
const getSelectedNodes = (): LGraphNode[] => {
@@ -410,18 +416,18 @@ export function useCoreCommands(): ComfyCommand[] {
label: 'Toggle Theme (Dark/Light)',
versionAdded: '1.3.12',
function: (() => {
let previousDarkTheme: string = 'dark'
let previousDarkTheme: string = DEFAULT_DARK_COLOR_PALETTE.id
let previousLightTheme: string = DEFAULT_LIGHT_COLOR_PALETTE.id
// Official light theme is the only light theme supported now.
const isDarkMode = (themeId: string) => themeId !== 'light'
return () => {
const settingStore = useSettingStore()
const currentTheme = settingStore.get('Comfy.ColorPalette')
if (isDarkMode(currentTheme)) {
previousDarkTheme = currentTheme
settingStore.set('Comfy.ColorPalette', 'light')
} else {
const theme = colorPaletteStore.completedActivePalette
if (theme.light_theme) {
previousLightTheme = theme.id
settingStore.set('Comfy.ColorPalette', previousDarkTheme)
} else {
previousDarkTheme = theme.id
settingStore.set('Comfy.ColorPalette', previousLightTheme)
}
}
})()

View File

@@ -3,7 +3,9 @@ import { computed, ref } from 'vue'
import {
CORE_COLOR_PALETTES,
DEFAULT_COLOR_PALETTE
DEFAULT_COLOR_PALETTE,
DEFAULT_DARK_COLOR_PALETTE,
DEFAULT_LIGHT_COLOR_PALETTE
} from '@/constants/coreColorPalettes'
import type {
ColorPalettes,
@@ -63,20 +65,24 @@ export const useColorPaletteStore = defineStore('colorPalette', () => {
palette.colors.comfy_base['comfy-menu-bg']
}
const defaultPalette = palette.light_theme
? DEFAULT_LIGHT_COLOR_PALETTE
: DEFAULT_DARK_COLOR_PALETTE
return {
...palette,
colors: {
...palette.colors,
node_slot: {
...DEFAULT_COLOR_PALETTE.colors.node_slot,
...defaultPalette.colors.node_slot,
...palette.colors.node_slot
},
litegraph_base: {
...DEFAULT_COLOR_PALETTE.colors.litegraph_base,
...defaultPalette.colors.litegraph_base,
...palette.colors.litegraph_base
},
comfy_base: {
...DEFAULT_COLOR_PALETTE.colors.comfy_base,
...defaultPalette.colors.comfy_base,
...palette.colors.comfy_base
}
}

View File

@@ -92,7 +92,8 @@ export const paletteSchema = z
.object({
id: z.string(),
name: z.string(),
colors: partialColorsSchema
colors: partialColorsSchema,
light_theme: z.boolean().optional()
})
.passthrough()

View File

@@ -13,7 +13,7 @@
import { useEventListener } from '@vueuse/core'
import type { ToastMessageOptions } from 'primevue/toast'
import { useToast } from 'primevue/usetoast'
import { computed, onBeforeUnmount, onMounted, watch, watchEffect } from 'vue'
import { onBeforeUnmount, onMounted, watch, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import BrowserTabTitle from '@/components/BrowserTabTitle.vue'
@@ -41,6 +41,7 @@ import {
import { useServerConfigStore } from '@/stores/serverConfigStore'
import { useSettingStore } from '@/stores/settingStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { StatusWsMessageStatus } from '@/types/apiTypes'
@@ -51,18 +52,16 @@ const { t } = useI18n()
const toast = useToast()
const settingStore = useSettingStore()
const executionStore = useExecutionStore()
const theme = computed<string>(() => settingStore.get('Comfy.ColorPalette'))
const colorPaletteStore = useColorPaletteStore()
watch(
theme,
() => colorPaletteStore.completedActivePalette,
(newTheme) => {
const DARK_THEME_CLASS = 'dark-theme'
const isDarkTheme = newTheme !== 'light'
if (isDarkTheme) {
document.body.classList.add(DARK_THEME_CLASS)
} else {
if (newTheme.light_theme) {
document.body.classList.remove(DARK_THEME_CLASS)
} else {
document.body.classList.add(DARK_THEME_CLASS)
}
},
{ immediate: true }