Compare commits

...

2 Commits

Author SHA1 Message Date
bymyself
49e5207c47 fix: add h-full to LivePreview img to prevent clipping in overflow-hidden wrapper
Amp-Thread-ID: https://ampcode.com/threads/T-019cbd6e-8879-7461-9e85-1775c81626fe
2026-03-05 16:16:17 -08:00
bymyself
ce16416cd8 feat: support transparent background for preview components
Remove solid backgrounds (bg-node-component-surface, bg-muted-background)
from ImagePreview, VideoPreview, and LivePreview so images/videos with
alpha channels blend naturally with the node surface.

Add opt-in Comfy.Preview.CheckerboardBackground setting that renders a
checkerboard pattern behind previews for inspecting transparency.

- Add bg-checkerboard @utility with repeating-conic-gradient
- Add --checkerboard-color-1/2 tokens for light and dark themes
- Register setting in Zod schema and core settings

Amp-Thread-ID: https://ampcode.com/threads/T-019cbd5a-243d-751c-904e-1026454275f6
2026-03-05 16:16:17 -08:00
6 changed files with 67 additions and 10 deletions

View File

@@ -290,6 +290,8 @@
--border-subtle: var(--color-smoke-400);
--muted-background: var(--color-smoke-700);
--accent-background: var(--color-smoke-800);
--checkerboard-color-1: var(--color-white);
--checkerboard-color-2: #cccccc;
/* Component/Node tokens from design system light */
--component-node-background: var(--color-white);
@@ -437,6 +439,8 @@
--border-subtle: var(--color-charcoal-300);
--muted-background: var(--color-charcoal-100);
--accent-background: var(--color-charcoal-100);
--checkerboard-color-1: #3a3a3a;
--checkerboard-color-2: #2a2a2a;
/* Component/Node tokens from design dark system */
--component-node-background: var(--color-charcoal-600);
@@ -667,6 +671,14 @@
}
/* =================== End Custom Scrollbar (cross-browser) =================== */
@utility bg-checkerboard {
background-image: repeating-conic-gradient(
var(--checkerboard-color-1) 0% 25%,
var(--checkerboard-color-2) 0% 50%
);
background-size: 16px 16px;
}
/* Everthing below here to be cleaned up over time. */
body {

View File

@@ -1247,6 +1247,16 @@ export const CORE_SETTINGS: SettingParams[] = [
experimental: true,
versionAdded: '1.40.0'
},
{
id: 'Comfy.Preview.CheckerboardBackground',
category: ['Comfy', 'Preview'],
name: 'Show checkerboard background on previews',
tooltip:
'Display a checkerboard pattern behind image and video previews to visualize transparency and alpha channels.',
type: 'boolean',
defaultValue: false,
versionAdded: '1.41.11'
},
{
id: 'Comfy.RightSidePanel.ShowErrorsTab',
category: ['Comfy', 'Error System'],

View File

@@ -7,7 +7,12 @@
<!-- Video Wrapper -->
<div
ref="videoWrapperEl"
class="relative flex flex-1 overflow-hidden rounded-[5px] bg-node-component-surface"
:class="
cn(
'relative flex flex-1 overflow-hidden rounded-[5px]',
showCheckerboard && 'bg-checkerboard'
)
"
tabindex="0"
role="region"
:aria-label="$t('g.videoPreview')"
@@ -123,6 +128,7 @@ import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { downloadFile } from '@/base/common/downloadUtil'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useNodeOutputStore } from '@/stores/nodeOutputStore'
import { cn } from '@/utils/tailwindUtil'
@@ -137,6 +143,9 @@ const props = defineProps<VideoPreviewProps>()
const { t } = useI18n()
const nodeOutputStore = useNodeOutputStore()
const showCheckerboard = computed(() =>
useSettingStore().get('Comfy.Preview.CheckerboardBackground')
)
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'

View File

@@ -7,7 +7,12 @@
<!-- Image Wrapper -->
<div
ref="imageWrapperEl"
class="min-h-0 flex-1 flex w-full overflow-hidden rounded-[5px] bg-muted-background relative"
:class="
cn(
'min-h-0 flex-1 flex w-full overflow-hidden rounded-[5px] relative',
showCheckerboard && 'bg-checkerboard'
)
"
tabindex="0"
role="img"
:aria-label="$t('g.imagePreview')"
@@ -128,8 +133,10 @@ import { useI18n } from 'vue-i18n'
import { downloadFile } from '@/base/common/downloadUtil'
import { useMaskEditor } from '@/composables/maskeditor/useMaskEditor'
import { useSettingStore } from '@/platform/settings/settingStore'
import { app } from '@/scripts/app'
import { useNodeOutputStore } from '@/stores/nodeOutputStore'
import { cn } from '@/utils/tailwindUtil'
interface ImagePreviewProps {
/** Array of image URLs to display */
@@ -143,6 +150,9 @@ const props = defineProps<ImagePreviewProps>()
const { t } = useI18n()
const maskEditor = useMaskEditor()
const nodeOutputStore = useNodeOutputStore()
const showCheckerboard = computed(() =>
useSettingStore().get('Comfy.Preview.CheckerboardBackground')
)
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'

View File

@@ -7,14 +7,23 @@
<i-lucide:image-off class="mb-1 size-8 text-smoke-500" />
<p class="text-xs text-smoke-400">{{ $t('g.imageFailedToLoad') }}</p>
</div>
<img
<div
v-else
:src="imageUrl"
:alt="$t('g.liveSamplingPreview')"
class="pointer-events-none w-full object-contain contain-size min-h-55 flex-1"
@load="handleImageLoad"
@error="handleImageError"
/>
:class="
cn(
'min-h-55 flex-1 overflow-hidden',
showCheckerboard && 'bg-checkerboard'
)
"
>
<img
:src="imageUrl"
:alt="$t('g.liveSamplingPreview')"
class="pointer-events-none h-full w-full object-contain contain-size"
@load="handleImageLoad"
@error="handleImageError"
/>
</div>
<div class="text-node-component-header-text mt-1 text-center text-xs">
{{
imageError
@@ -26,7 +35,10 @@
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { computed, ref, watch } from 'vue'
import { useSettingStore } from '@/platform/settings/settingStore'
import { cn } from '@/utils/tailwindUtil'
interface LivePreviewProps {
imageUrl: string
@@ -34,6 +46,9 @@ interface LivePreviewProps {
const props = defineProps<LivePreviewProps>()
const showCheckerboard = computed(() =>
useSettingStore().get('Comfy.Preview.CheckerboardBackground')
)
const actualDimensions = ref<string | null>(null)
const imageError = ref(false)

View File

@@ -347,6 +347,7 @@ const zSettings = z.object({
'Comfy.Pointer.ClickBufferTime': z.number(),
'Comfy.Pointer.ClickDrift': z.number(),
'Comfy.Pointer.DoubleClickTime': z.number(),
'Comfy.Preview.CheckerboardBackground': z.boolean(),
'Comfy.PreviewFormat': z.string(),
'Comfy.PromptFilename': z.boolean(),
'Comfy.Sidebar.Location': z.enum(['left', 'right']),