[style] update style of mask editor button on Vue node image preview (#6060)

Updates style of mask editor button on Vue nodes image preview overlay
to align with
[design](https://www.figma.com/design/31uH3r4x3xbIctuRWYW6NM/V3---Vue-Nodes?node-id=7744-84270&m=dev).
Also makes the custom mask have color be derived from text color class.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6060-style-update-style-of-mask-editor-button-on-Vue-node-image-preview-28c6d73d36508111a562c6a22c64f027)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Christian Byrne
2025-10-16 21:02:55 -07:00
committed by GitHub
parent 653cf64e01
commit ad5be8ec70
4 changed files with 30 additions and 13 deletions

View File

@@ -63,6 +63,7 @@
--color-sand-200: #d6cfc2; --color-sand-200: #d6cfc2;
--color-sand-300: #888682; --color-sand-300: #888682;
--color-pure-black: #000000;
--color-pure-white: #ffffff; --color-pure-white: #ffffff;
--color-slate-100: #9c9eab; --color-slate-100: #9c9eab;
@@ -144,6 +145,9 @@
--content-hover-bg: #adadad; --content-hover-bg: #adadad;
--content-hover-fg: #000; --content-hover-fg: #000;
--button-surface: var(--color-pure-white);
--button-surface-contrast: var(--color-pure-black);
/* Code styling colors for help menu*/ /* Code styling colors for help menu*/
--code-text-color: rgb(0 122 255 / 1); --code-text-color: rgb(0 122 255 / 1);
--code-bg-color: rgb(96 165 250 / 0.2); --code-bg-color: rgb(96 165 250 / 0.2);
@@ -201,6 +205,8 @@
.dark-theme { .dark-theme {
--accent-primary: var(--color-pure-white); --accent-primary: var(--color-pure-white);
--backdrop: var(--color-neutral-900); --backdrop: var(--color-neutral-900);
--button-surface: var(--color-charcoal-600);
--button-surface-contrast: var(--color-pure-white);
--button-hover-surface: var(--color-charcoal-600); --button-hover-surface: var(--color-charcoal-600);
--button-active-surface: var(--color-charcoal-600); --button-active-surface: var(--color-charcoal-600);
--dialog-surface: var(--color-neutral-700); --dialog-surface: var(--color-neutral-700);
@@ -246,6 +252,8 @@
--color-backdrop: var(--backdrop); --color-backdrop: var(--backdrop);
--color-button-hover-surface: var(--button-hover-surface); --color-button-hover-surface: var(--button-hover-surface);
--color-button-active-surface: var(--button-active-surface); --color-button-active-surface: var(--button-active-surface);
--color-button-surface: var(--button-surface);
--color-button-surface-contrast: var(--button-surface-contrast);
--color-dialog-surface: var(--dialog-surface); --color-dialog-surface: var(--dialog-surface);
--color-interface-menu-component-surface-hovered: var(--interface-menu-component-surface-hovered); --color-interface-menu-component-surface-hovered: var(--interface-menu-component-surface-hovered);
--color-interface-menu-component-surface-selected: var(--interface-menu-component-surface-selected); --color-interface-menu-component-surface-selected: var(--interface-menu-component-surface-selected);

View File

@@ -1,14 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" class="" viewBox="0 0 16 16" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" class="" viewBox="0 0 16 16" fill="none">
<g clip-path="url(#clip0_704_2695)"> <g clip-path="url(#clip0_704_2695)">
<path d="M6.05048 2C5.52055 7.29512 9.23033 10.4722 14 9.94267" stroke="#9C9EAB" stroke-width="1.3"/> <path d="M6.05048 2C5.52055 7.29512 9.23033 10.4722 14 9.94267" stroke="currentColor" stroke-width="1.3"/>
<path d="M6.5 5.5L10 2" stroke="#9C9EAB" stroke-width="1.3" stroke-linecap="round"/> <path d="M6.5 5.5L10 2" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
<path d="M8 8L12.5 3.5" stroke="#9C9EAB" stroke-width="1.3" stroke-linecap="square"/> <path d="M8 8L12.5 3.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="square"/>
<path d="M10.5 9.5L14 6" stroke="#9C9EAB" stroke-width="1.3" stroke-linecap="round"/> <path d="M10.5 9.5L14 6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/>
<path d="M7.99992 14.6667C11.6818 14.6667 14.6666 11.6819 14.6666 8.00004C14.6666 4.31814 11.6818 1.33337 7.99992 1.33337C4.31802 1.33337 1.33325 4.31814 1.33325 8.00004C1.33325 11.6819 4.31802 14.6667 7.99992 14.6667Z" stroke="#9C9EAB" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.99992 14.6667C11.6818 14.6667 14.6666 11.6819 14.6666 8.00004C14.6666 4.31814 11.6818 1.33337 7.99992 1.33337C4.31802 1.33337 1.33325 4.31814 1.33325 8.00004C1.33325 11.6819 4.31802 14.6667 7.99992 14.6667Z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/>
</g> </g>
<defs> <defs>
<clipPath id="clip0_704_2695"> <clipPath id="clip0_704_2695">
<rect width="16" height="16" fill="white"/> <rect width="16" height="16" fill="white"/>
</clipPath> </clipPath>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 938 B

After

Width:  |  Height:  |  Size: 964 B

View File

@@ -41,21 +41,21 @@
/> />
<!-- Floating Action Buttons (appear on hover) --> <!-- Floating Action Buttons (appear on hover) -->
<div v-if="isHovered" class="actions absolute top-2 right-2 flex gap-1"> <div v-if="isHovered" class="actions absolute top-2 right-2 flex gap-2.5">
<!-- Mask/Edit Button --> <!-- Mask/Edit Button -->
<button <button
v-if="!hasMultipleImages" v-if="!hasMultipleImages"
class="action-btn cursor-pointer rounded-lg border-0 bg-white p-2 text-black shadow-sm transition-all duration-200 hover:bg-gray-100" :class="actionButtonClass"
:title="$t('g.editOrMaskImage')" :title="$t('g.editOrMaskImage')"
:aria-label="$t('g.editOrMaskImage')" :aria-label="$t('g.editOrMaskImage')"
@click="handleEditMask" @click="handleEditMask"
> >
<i class="icon-[lucide--venetian-mask] h-4 w-4" /> <i-comfy:mask class="h-4 w-4" />
</button> </button>
<!-- Download Button --> <!-- Download Button -->
<button <button
class="action-btn cursor-pointer rounded-lg border-0 bg-white p-2 text-black shadow-sm transition-all duration-200 hover:bg-gray-100" :class="actionButtonClass"
:title="$t('g.downloadImage')" :title="$t('g.downloadImage')"
:aria-label="$t('g.downloadImage')" :aria-label="$t('g.downloadImage')"
@click="handleDownload" @click="handleDownload"
@@ -65,7 +65,7 @@
<!-- Close Button --> <!-- Close Button -->
<button <button
class="action-btn cursor-pointer rounded-lg border-0 bg-white p-2 text-black shadow-sm transition-all duration-200 hover:bg-gray-100" :class="actionButtonClass"
:title="$t('g.removeImage')" :title="$t('g.removeImage')"
:aria-label="$t('g.removeImage')" :aria-label="$t('g.removeImage')"
@click="handleRemove" @click="handleRemove"
@@ -138,6 +138,9 @@ const { t } = useI18n()
const commandStore = useCommandStore() const commandStore = useCommandStore()
const nodeOutputStore = useNodeOutputStore() const nodeOutputStore = useNodeOutputStore()
const actionButtonClass =
'flex h-8 min-h-8 items-center justify-center gap-2.5 rounded-lg border-0 bg-button-surface px-2 py-2 text-button-surface-contrast shadow-sm transition-colors duration-200 hover:bg-button-hover-surface focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-button-surface-contrast focus-visible:ring-offset-2 focus-visible:ring-offset-transparent cursor-pointer'
// Component state // Component state
const currentIndex = ref(0) const currentIndex = ref(0)
const isHovered = ref(false) const isHovered = ref(false)

View File

@@ -113,7 +113,12 @@ describe('ImagePreview', () => {
// Action buttons should now be visible // Action buttons should now be visible
expect(wrapper.find('.actions').exists()).toBe(true) expect(wrapper.find('.actions').exists()).toBe(true)
expect(wrapper.findAll('.action-btn')).toHaveLength(2) // download, remove (no mask for multiple images) // For multiple images: download and remove buttons (no mask button)
expect(wrapper.find('[aria-label="Download image"]').exists()).toBe(true)
expect(wrapper.find('[aria-label="Remove image"]').exists()).toBe(true)
expect(wrapper.find('[aria-label="Edit or mask image"]').exists()).toBe(
false
)
}) })
it('hides action buttons when not hovering', async () => { it('hides action buttons when not hovering', async () => {
@@ -203,8 +208,9 @@ describe('ImagePreview', () => {
await navigationDots[1].trigger('click') await navigationDots[1].trigger('click')
await nextTick() await nextTick()
// After clicking, component shows loading state (Skeleton) // After clicking, component shows loading state (Skeleton), not img
expect(wrapper.find('skeleton-stub').exists()).toBe(true) expect(wrapper.find('skeleton-stub').exists()).toBe(true)
expect(wrapper.find('img').exists()).toBe(false)
// Simulate image load event to clear loading state // Simulate image load event to clear loading state
const component = wrapper.vm as any const component = wrapper.vm as any