Style: Make components themeable (#5908)

## Summary

Replace color/dark-color pairs in components with design tokens to allow
for easy overriding.
<!-- Also standardizes the icon pattern to simplify the tailwind config.
-->

## Changes

- **What**: Token based colors, for now, mostly.
- **Breaking**: Got approval from Design to collapse some very similar
pairs of colors that seem to have diverged in implementations over time.
Some of the colors might be a little different, but we can tweak them
later.

## Review Focus

Still have quite a few places from which to remove `dark-theme`, but
this at least gets the theming much closer.
Need to decide if I want to keep going in here or cut this and do the
rest in a subsequent PR.

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5908-WIP-Make-components-themeable-2816d73d365081ffbc05d189fe71084b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Alexander Brown
2025-10-06 16:27:08 -07:00
committed by GitHub
parent 51f0f111ea
commit e7745eb2be
50 changed files with 235 additions and 105 deletions

View File

@@ -12,6 +12,16 @@ import { downloadBlob, uploadFile } from '@/scripts/utils'
import { useNodeDefStore } from '@/stores/nodeDefStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
const THEME_PROPERTY_MAP = {
NODE_BOX_OUTLINE_COLOR: 'node-component-border',
NODE_DEFAULT_BGCOLOR: 'node-component-surface',
NODE_DEFAULT_BOXCOLOR: 'node-component-header-icon',
NODE_DEFAULT_COLOR: 'node-component-header-surface',
NODE_TITLE_COLOR: 'node-component-header',
WIDGET_BGCOLOR: 'node-component-widget-input-surface',
WIDGET_TEXT_COLOR: 'node-component-widget-input'
} as const satisfies Partial<Record<keyof Colors['litegraph_base'], string>>
export const useColorPaletteService = () => {
const colorPaletteStore = useColorPaletteStore()
const settingStore = useSettingStore()
@@ -78,6 +88,40 @@ export const useColorPaletteService = () => {
Object.assign(LGraphCanvas.link_type_colors, types, linkColorPalette)
}
function validThemeProp(
propertyMaybe: unknown
): propertyMaybe is keyof typeof THEME_PROPERTY_MAP {
return (
(propertyMaybe as keyof typeof THEME_PROPERTY_MAP) in THEME_PROPERTY_MAP
)
}
function loadLitegraphForVueNodes(
palette: Colors['litegraph_base'],
colorPaletteId: string
) {
if (!palette) return
const rootStyle = document.getElementById('vue-app')?.style
if (!rootStyle) return
for (const themeVar of Object.keys(THEME_PROPERTY_MAP)) {
if (!validThemeProp(themeVar)) {
continue
}
const cssVar = THEME_PROPERTY_MAP[themeVar]
if (colorPaletteId === 'dark' || colorPaletteId === 'light') {
rootStyle.removeProperty(`--${cssVar}`)
continue
}
const valueMaybe = palette[themeVar]
if (valueMaybe) {
rootStyle.setProperty(`--${cssVar}`, valueMaybe)
} else {
rootStyle.removeProperty(`--${cssVar}`)
}
}
}
/**
* Loads the LiteGraph color palette.
*
@@ -120,20 +164,19 @@ export const useColorPaletteService = () => {
* @param comfyColorPalette - The palette to set.
*/
const loadComfyColorPalette = (comfyColorPalette: Colors['comfy_base']) => {
if (comfyColorPalette) {
const rootStyle = document.documentElement.style
for (const [key, value] of Object.entries(comfyColorPalette)) {
rootStyle.setProperty('--' + key, value)
}
const backgroundImage = settingStore.get('Comfy.Canvas.BackgroundImage')
if (backgroundImage) {
rootStyle.setProperty(
'--bg-img',
`url('${backgroundImage}') no-repeat center /cover`
)
} else {
rootStyle.removeProperty('--bg-img')
}
if (!comfyColorPalette) return
const rootStyle = document.documentElement.style
for (const [key, value] of Object.entries(comfyColorPalette)) {
rootStyle.setProperty('--' + key, value)
}
const backgroundImage = settingStore.get('Comfy.Canvas.BackgroundImage')
if (backgroundImage) {
rootStyle.setProperty(
'--bg-img',
`url('${backgroundImage}') no-repeat center /cover`
)
} else {
rootStyle.removeProperty('--bg-img')
}
}
@@ -151,6 +194,10 @@ export const useColorPaletteService = () => {
const completedPalette = colorPaletteStore.completePalette(colorPalette)
loadLinkColorPalette(completedPalette.colors.node_slot)
loadLiteGraphColorPalette(completedPalette.colors.litegraph_base)
loadLitegraphForVueNodes(
completedPalette.colors.litegraph_base,
colorPaletteId
)
loadComfyColorPalette(completedPalette.colors.comfy_base)
app.canvas.setDirty(true, true)

View File

@@ -121,8 +121,7 @@ export const useDialogService = () => {
pt: {
pcCloseButton: {
root: {
class:
'bg-gray-500 dark-theme:bg-neutral-700 w-9 h-9 p-1.5 rounded-full text-white'
class: 'bg-dialog-surface w-9 h-9 p-1.5 rounded-full text-white'
}
},
header: { class: 'py-0! px-6 m-0! h-[68px]' },
@@ -469,7 +468,7 @@ export const useDialogService = () => {
pcCloseButton: {
root: {
class:
'!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5 bg-gray-500 dark-theme:bg-neutral-700 text-white'
'!w-7 !h-7 !border-none !outline-none !p-2 !m-1.5 bg-dialog-surface text-white'
}
}
},