Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bc2c3f7
style: first step in making the nodes themeable: LGraphNode
DrJKL Oct 3, 2025
306f563
style: More variable to token migration
DrJKL Oct 3, 2025
c373450
style: More migrations, renderer/extension/vueNodes/components
DrJKL Oct 3, 2025
326a6b6
style: tokens for tooltips
DrJKL Oct 3, 2025
1a21d6d
style: More migrations. Some of these seem very different than other …
DrJKL Oct 3, 2025
7232e5d
style: More migrations, dialogs as a top level category?
DrJKL Oct 3, 2025
110e29c
style: Migrate subgraph node pieces. Why aren't these using the base …
DrJKL Oct 3, 2025
5d27651
style: add targetable color token for the node header
DrJKL Oct 4, 2025
ed3a8af
WIP: Starting to sync palette colors to use in Vue nodes
DrJKL Oct 4, 2025
e31517b
fix: Wrong backdrop color for the status indicator
DrJKL Oct 4, 2025
d9606ef
WIP: More property mappings
DrJKL Oct 4, 2025
308c93a
style: Make sure the color applies to the subgraph button too
DrJKL Oct 4, 2025
70f0a6f
style: Fix border property and collapsed header rounding
DrJKL Oct 4, 2025
a70dc33
style: Change enter subgraph icon
DrJKL Oct 4, 2025
03043e2
fix:Special cases for light/dark mode
DrJKL Oct 4, 2025
4201699
fix: Make the collapse button a button
DrJKL Oct 4, 2025
112a782
test: update unit tests
DrJKL Oct 5, 2025
72470bd
cleanup: remove comprehensiveness check toggle @Myestery
DrJKL Oct 5, 2025
3673f7a
test: Update locator for selected nodes
DrJKL Oct 5, 2025
ada29cd
[automated] Update test expectations
invalid-email-address Oct 6, 2025
f701005
fix: Adjust border color as in https://github.com/Comfy-Org/ComfyUI_f…
DrJKL Oct 6, 2025
3e7bde3
[automated] Update test expectations
invalid-email-address Oct 6, 2025
349fb2c
Merge branch 'main' into drjkl/leitmotif
DrJKL Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions browser_tests/fixtures/VueNodeHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ export class VueNodeHelpers {
* Get locator for selected Vue node components (using visual selection indicators)
*/
get selectedNodes(): Locator {
return this.page.locator(
'[data-node-id].outline-black, [data-node-id].outline-white'
)
return this.page.locator('[data-node-id].outline-node-component-outline')
}

/**
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions browser_tests/tests/vueNodes/nodeStates/collapse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ test.describe('Vue Node Collapse', () => {

// Check initial expanded state icon
let iconClass = await vueNode.getCollapseIconClass()
expect(iconClass).toContain('pi-chevron-down')
expect(iconClass).not.toContain('-rotate-90')

// Collapse and check icon
await vueNode.toggleCollapse()
iconClass = await vueNode.getCollapseIconClass()
expect(iconClass).toContain('pi-chevron-right')
expect(iconClass).toContain('-rotate-90')

// Expand and check icon
await vueNode.toggleCollapse()
iconClass = await vueNode.getCollapseIconClass()
expect(iconClass).toContain('pi-chevron-down')
expect(iconClass).not.toContain('-rotate-90')
})

test('should preserve title when collapsing/expanding', async ({
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 83 additions & 5 deletions packages/design-system/src/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,90 @@
--color-dark-elevation-2: rgba(from white r g b / 0.03);
}

:root {
--backdrop: var(--color-white);
--dialog-surface: var(--color-neutral-200);
--node-component-border: var(--color-gray-400);
--node-component-executing: var(--color-blue-500);
--node-component-header: var(--fg-color);
--node-component-header-icon: var(--color-stone-200);
--node-component-header-surface: var(--color-white);
--node-component-outline: var(--color-black);
--node-component-ring: rgb(from var(--color-gray-500) r g b / 50%);
--node-component-slot-dot-outline-opacity-mult: 1;
--node-component-slot-dot-outline-opacity: 5%;
--node-component-slot-dot-outline: var(--color-black);
--node-component-slot-text: var(--color-stone-200);
--node-component-surface-highlight: var(--color-stone-100);
--node-component-surface-hovered: var(--color-charcoal-400);
--node-component-surface-selected: var(--color-charcoal-200);
--node-component-surface: var(--color-white);
--node-component-tooltip: var(--color-charcoal-700);
--node-component-tooltip-border: var(--color-sand-100);
--node-component-tooltip-surface: var(--color-white);
--node-component-widget-input: var(--fg-color);
--node-component-widget-input-surface: rgb(from var(--color-zinc-500) r g b / 10%);
--node-component-widget-skeleton-surface: var(--color-zinc-300);
--node-stroke: var(--color-stone-100);
}

.dark-theme {
--backdrop: var(--color-neutral-900);
--dialog-surface: var(--color-neutral-700);
--node-component-border: var(--color-stone-200);
--node-component-header-icon: var(--color-slate-300);
--node-component-header-surface: var(--color-charcoal-800);
--node-component-outline: var(--color-white);
--node-component-ring: rgb(var(--color-gray-500) / 20%);
--node-component-slot-dot-outline-opacity: 10%;
--node-component-slot-dot-outline: var(--color-white);
--node-component-slot-text: var(--color-slate-200);
--node-component-surface-highlight: var(--color-slate-100);
--node-component-surface-hovered: var(--color-charcoal-400);
--node-component-surface-selected: var(--color-charcoal-200);
--node-component-surface: var(--color-charcoal-800);
--node-component-tooltip: var(--color-white);
--node-component-tooltip-border: var(--color-slate-300);
--node-component-tooltip-surface: var(--color-charcoal-800);
--node-component-widget-skeleton-surface: var(--color-zinc-800);
--node-stroke: var(--color-slate-100);
}

@theme inline {
--color-node-component-surface: var(--color-charcoal-600);
--color-node-component-surface-highlight: var(--color-slate-100);
--color-node-component-surface-hovered: var(--color-charcoal-400);
--color-node-component-surface-selected: var(--color-charcoal-200);
--color-node-stroke: var(--color-stone-100);
--color-backdrop: var(--backdrop);
--color-dialog-surface: var(--dialog-surface);
--color-node-component-border: var(--node-component-border);
--color-node-component-executing: var(--node-component-executing);
--color-node-component-header: var(--node-component-header);
--color-node-component-header-icon: var(--node-component-header-icon);
--color-node-component-header-surface: var(--node-component-header-surface);
--color-node-component-outline: var(--node-component-outline);
--color-node-component-ring: var(--node-component-ring);
--color-node-component-slot-dot-outline: rgb(
from var(--node-component-slot-dot-outline) r g b /
calc(
var(--node-component-slot-dot-outline-opacity) *
var(--node-component-slot-dot-outline-opacity-mult)
)
);
--color-node-component-slot-text: var(--node-component-slot-text);
--color-node-component-surface-highlight: var(
--node-component-surface-highlight
);
--color-node-component-surface-hovered: var(--node-component-surface-hovered);
--color-node-component-surface-selected: var(--component-surface-selected);
--color-node-component-surface: var(--node-component-surface);
--color-node-component-tooltip: var(--node-component-tooltip);
--color-node-component-tooltip-border: var(--node-component-tooltip-border);
--color-node-component-tooltip-surface: var(--node-component-tooltip-surface);
--color-node-component-widget-input: var(--node-component-widget-input);
--color-node-component-widget-input-surface: var(
--node-component-widget-input-surface
);
--color-node-component-widget-skeleton-surface: var(
--node-component-widget-skeleton-surface
);
--color-node-stroke: var(--node-stroke);
}

@custom-variant dark-theme {
Expand Down
14 changes: 7 additions & 7 deletions src/components/custom/widget/WorkflowTemplateSelectorDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
<!-- Title -->
<span
v-if="isLoading"
class="inline-block h-8 w-48 bg-neutral-200 dark-theme:bg-neutral-700 rounded animate-pulse"
class="inline-block h-8 w-48 bg-dialog-surface rounded animate-pulse"
></span>

<!-- Template Cards Grid -->
Expand All @@ -148,7 +148,7 @@
<CardTop ratio="landscape">
<template #default>
<div
class="w-full h-full bg-neutral-200 dark-theme:bg-neutral-700 animate-pulse"
class="w-full h-full bg-dialog-surface animate-pulse"
></div>
</template>
</CardTop>
Expand All @@ -157,10 +157,10 @@
<CardBottom>
<div class="px-4 py-3">
<div
class="h-6 bg-neutral-200 dark-theme:bg-neutral-700 rounded animate-pulse mb-2"
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
></div>
<div
class="h-4 bg-neutral-200 dark-theme:bg-neutral-700 rounded animate-pulse"
class="h-4 bg-dialog-surface rounded animate-pulse"
></div>
</div>
</CardBottom>
Expand Down Expand Up @@ -323,7 +323,7 @@
<CardTop ratio="square">
<template #default>
<div
class="w-full h-full bg-neutral-200 dark-theme:bg-neutral-700 animate-pulse"
class="w-full h-full bg-dialog-surface animate-pulse"
></div>
</template>
</CardTop>
Expand All @@ -332,10 +332,10 @@
<CardBottom>
<div class="px-4 py-3">
<div
class="h-6 bg-neutral-200 dark-theme:bg-neutral-700 rounded animate-pulse mb-2"
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
></div>
<div
class="h-4 bg-neutral-200 dark-theme:bg-neutral-700 rounded animate-pulse"
class="h-4 bg-dialog-surface rounded animate-pulse"
></div>
</div>
</CardBottom>
Expand Down
2 changes: 1 addition & 1 deletion src/components/topbar/WorkflowTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<div class="relative">
<span
v-if="shouldShowStatusIndicator"
class="group-hover:hidden absolute font-bold text-2xl top-1/2 left-1/2 -translate-1/2 z-10 bg-(--comfy-menu-secondary-bg) w-4"
class="group-hover:hidden absolute font-bold text-2xl top-1/2 left-1/2 -translate-1/2 z-10 bg-(--comfy-menu-bg) w-4"
>•</span
>
<Button
Expand Down
4 changes: 2 additions & 2 deletions src/core/graph/subgraph/SubgraphNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ onBeforeUnmount(() => {
/>
<div
v-if="filteredActive.length"
class="pt-1 pb-4 border-b-1 border-sand-100 dark-theme:border-charcoal-600"
class="pt-1 pb-4 border-b-1 border-node-component-border"
>
<div class="flex py-0 px-4 justify-between">
<div class="text-slate-100 text-[9px] font-semibold uppercase">
Expand Down Expand Up @@ -302,7 +302,7 @@ onBeforeUnmount(() => {
</div>
<div
v-if="recommendedWidgets.length"
class="justify-center flex py-4 border-t-1 border-sand-100 dark-theme:border-charcoal-600"
class="justify-center flex py-4 border-t-1 border-node-component-border"
>
<Button
size="small"
Expand Down
2 changes: 1 addition & 1 deletion src/core/graph/subgraph/SubgraphNodeWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defineEmits<{
function classes() {
return cn(
'flex py-1 pr-4 pl-0 break-all rounded items-center gap-1',
'bg-pure-white dark-theme:bg-charcoal-800',
'bg-node-component-surface',
props.isDraggable
? 'drag-handle cursor-grab [.is-draggable]:cursor-grabbing'
: ''
Expand Down
2 changes: 1 addition & 1 deletion src/core/graph/subgraph/useSubgraphNodeDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function showSubgraphNodeDialog() {
position: 'topright',
pt: {
root: {
class: 'bg-pure-white dark-theme:bg-charcoal-800 mt-22'
class: 'bg-node-component-surface mt-22'
},
header: {
class: 'h-8 text-xs ml-3'
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/extensions/minimap/MiniMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
</Button>

<hr
class="absolute top-5 bg-[#E1DED5] dark-theme:bg-[#262729] h-[1px] border-0"
class="absolute top-5 bg-node-component-border h-px border-0"
:style="{
width: containerStyles.width
}"
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/extensions/vueNodes/components/InputSlot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ const hasSlotError = computed(() => {

const errorClassesDot = computed(() => {
return hasSlotError.value
? 'ring-2 ring-error dark-theme:ring-error ring-offset-0 rounded-full'
? 'ring-2 ring-error ring-offset-0 rounded-full'
: ''
})

const labelClasses = computed(() =>
hasSlotError.value
? 'text-error dark-theme:text-error font-medium'
: 'dark-theme:text-slate-200 text-stone-200'
? 'text-error font-medium'
: 'text-node-component-slot-text'
)

const renderError = ref<string | null>(null)
Expand Down
21 changes: 10 additions & 11 deletions src/renderer/extensions/vueNodes/components/LGraphNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
:data-node-id="nodeData.id"
:class="
cn(
'bg-white dark-theme:bg-charcoal-800',
'bg-node-component-surface',
'lg-node absolute rounded-2xl touch-none',
'border-1 border-solid border-gray-400 dark-theme:border-stone-200',
'border-1 border-solid border-node-component-border',
// hover (only when node should handle events)
shouldHandleNodePointerEvents &&
'hover:ring-7 ring-gray-500/50 dark-theme:ring-gray-500/20',
'hover:ring-7 ring-node-component-ring',
'outline-transparent -outline-offset-2 outline-2',
borderClass,
outlineClass,
Expand Down Expand Up @@ -274,8 +274,7 @@ const hasCustomContent = computed(() => {
})

// Computed classes and conditions for better reusability
const separatorClasses =
'bg-sand-100 dark-theme:bg-charcoal-600 h-px mx-0 w-full lod-toggle'
const separatorClasses = 'bg-node-component-border h-px mx-0 w-full lod-toggle'
const progressClasses = 'h-2 bg-primary-500 transition-all duration-300'

const { latestPreviewUrl, shouldShowPreviewImg } = useNodePreviewState(
Expand All @@ -287,17 +286,17 @@ const { latestPreviewUrl, shouldShowPreviewImg } = useNodePreviewState(

const borderClass = computed(() => {
return (
(hasAnyError.value && 'border-error dark-theme:border-error') ||
(executing.value && 'border-blue-500')
(hasAnyError.value && 'border-error') ||
(executing.value && 'border-node-executing')
)
})

const outlineClass = computed(() => {
return (
return cn(
isSelected.value &&
((hasAnyError.value && 'outline-error dark-theme:outline-error') ||
(executing.value && 'outline-blue-500 dark-theme:outline-blue-500') ||
'outline-black dark-theme:outline-white')
((hasAnyError.value && 'outline-error ') ||
(executing.value && 'outline-node-executing') ||
'outline-node-component-outline')
)
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<template>
<div class="scale-75">
<div
class="bg-white dark-theme:bg-charcoal-800 lg-node absolute rounded-2xl border border-solid border-sand-100 dark-theme:border-charcoal-600 outline-transparent -outline-offset-2 outline-2 pointer-events-none"
class="bg-node-component-surface lg-node absolute rounded-2xl border border-solid border-node-component-border outline-transparent -outline-offset-2 outline-2 pointer-events-none"
>
<NodeHeader :node-data="nodeData" :readonly="readonly" />

<div
class="bg-sand-100 dark-theme:bg-charcoal-600 h-px mx-0 w-full mb-4"
/>
<div class="bg-node-component-border h-px mx-0 w-full mb-4" />

<div class="flex flex-col gap-4 pb-4">
<NodeSlots
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div
class="lod-fallback absolute inset-0 w-full h-full bg-zinc-300 dark-theme:bg-zinc-800"
class="lod-fallback absolute inset-0 w-full h-full bg-node-component-widget-skeleton-surface"
></div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,11 @@ describe('NodeHeader.vue', () => {
it('renders correct chevron icon based on collapsed prop', async () => {
const wrapper = mountHeader({ collapsed: false })
const expandedIcon = wrapper.get('i')
expect(expandedIcon.classes()).toContain('pi-chevron-down')
expect(expandedIcon.classes()).not.toContain('-rotate-90')

await wrapper.setProps({ collapsed: true })
const collapsedIcon = wrapper.get('i')
expect(collapsedIcon.classes()).toContain('pi-chevron-right')
expect(collapsedIcon.classes()).toContain('-rotate-90')
})

describe('Tooltips', () => {
Expand Down
Loading
Loading