Skip to content
32 changes: 32 additions & 0 deletions browser_tests/tests/confirmDialogTextWrap.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect } from '@playwright/test'

import { comfyPageFixture as test } from '../fixtures/ComfyPage'

test.describe('Confirm dialog text wrapping', { tag: ['@mobile'] }, () => {
test('@mobile confirm dialog buttons are visible with long unbreakable text', async ({
comfyPage
}) => {
const longFilename = 'workflow_checkpoint_' + 'a'.repeat(200) + '.json'

await comfyPage.page.evaluate((msg) => {
window
.app!.extensionManager.dialog.confirm({
title: 'Confirm',
type: 'default',
message: msg
})
.catch(() => {})
}, longFilename)

const dialog = comfyPage.page.getByRole('dialog')
await expect(dialog).toBeVisible()

const confirmButton = dialog.getByRole('button', { name: 'Confirm' })
await expect(confirmButton).toBeVisible()
await expect(confirmButton).toBeInViewport()

const cancelButton = dialog.getByRole('button', { name: 'Cancel' })
await expect(cancelButton).toBeVisible()
await expect(cancelButton).toBeInViewport()
})
})
2 changes: 1 addition & 1 deletion src/components/dialog/confirm/ConfirmBody.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
class="flex flex-col px-4 py-2 text-sm text-muted-foreground border-t border-border-default"
class="flex flex-col break-words px-4 py-2 text-sm text-muted-foreground border-t border-border-default"
>
<p v-if="promptTextReal">
{{ promptTextReal }}
Expand Down
2 changes: 1 addition & 1 deletion src/components/dialog/confirm/ConfirmFooter.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<section class="w-full flex gap-2 justify-end px-2 pb-2">
<section class="w-full flex flex-wrap gap-2 justify-end px-2 pb-2">
<Button :disabled variant="textonly" autofocus @click="$emit('cancel')">
{{ cancelTextX }}
</Button>
Expand Down
45 changes: 45 additions & 0 deletions src/components/dialog/content/ConfirmationDialogContent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import PrimeVue from 'primevue/config'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { ComponentProps } from 'vue-component-type-helpers'
import { createI18n } from 'vue-i18n'

import ConfirmationDialogContent from './ConfirmationDialogContent.vue'

type Props = ComponentProps<typeof ConfirmationDialogContent>

const i18n = createI18n({
legacy: false,
locale: 'en',
messages: { en: {} },
missingWarn: false,
fallbackWarn: false
})

describe('ConfirmationDialogContent', () => {
beforeEach(() => {
setActivePinia(createPinia())
})

function mountComponent(props: Partial<Props> = {}) {
return mount(ConfirmationDialogContent, {
global: {
plugins: [PrimeVue, i18n]
},
props: {
message: 'Test message',
type: 'default',
onConfirm: vi.fn(),
...props
} as Props
})
}

it('renders long messages without breaking layout', () => {
const longFilename =
'workflow_checkpoint_' + 'a'.repeat(200) + '.safetensors'
const wrapper = mountComponent({ message: longFilename })
expect(wrapper.text()).toContain(longFilename)
})
})
45 changes: 22 additions & 23 deletions src/components/dialog/content/ConfirmationDialogContent.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
<template>
<section class="prompt-dialog-content m-2 mt-4 flex flex-col gap-6">
<span>{{ message }}</span>
<ul v-if="itemList?.length" class="m-0 flex flex-col gap-2 pl-4">
<li v-for="item of itemList" :key="item">
{{ item }}
</li>
</ul>
<Message
v-if="hint"
icon="pi pi-info-circle"
severity="secondary"
size="small"
variant="simple"
>
{{ hint }}
</Message>
<div class="flex justify-end gap-4">
<section
class="m-2 mt-4 flex max-h-[70vh] flex-col gap-6 whitespace-pre-wrap break-words"
>
<div class="flex-1 overflow-y-auto">
<span>{{ message }}</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/components/dialog/content/ConfirmationDialogContent.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 4784


🏁 Script executed:

rg "overflow-y-auto" src/components --type vue -A 2 -B 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 97


🏁 Script executed:

rg "overflow-y-auto" src/components -A 2 -B 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 9356


Add min-h-0 to ensure the scroll container shrinks reliably in flex columns.

Without min-h-0, flex children with overflow-y-auto may not shrink below their content size in all browsers, preventing the scrollable area from functioning properly and allowing long content to push the action buttons off-screen. This pattern is consistently applied throughout the codebase (e.g., BaseModalLayout.vue, MembersPanelContent.vue).

✅ Suggested fix
-    <div class="flex-1 overflow-y-auto">
+    <div class="min-h-0 flex-1 overflow-y-auto">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<section
class="m-2 mt-4 flex max-h-[70vh] flex-col gap-6 whitespace-pre-wrap break-words"
>
<div class="flex-1 overflow-y-auto">
<span>{{ message }}</span>
<section
class="m-2 mt-4 flex max-h-[70vh] flex-col gap-6 whitespace-pre-wrap break-words"
>
<div class="min-h-0 flex-1 overflow-y-auto">
<span>{{ message }}</span>
🤖 Prompt for AI Agents
In `@src/components/dialog/content/ConfirmationDialogContent.vue` around lines 2 -
6, The scroll container in ConfirmationDialogContent.vue currently uses the div
with class "flex-1 overflow-y-auto" which can fail to shrink in flex columns;
update that element (the div containing the message) to include min-h-0 (e.g.,
change its class to include "min-h-0") so the overflow-y-auto container can
shrink reliably and allow scrolling without pushing action buttons off-screen.

<ul v-if="itemList?.length" class="m-0 mt-2 flex flex-col gap-2 pl-4">
<li v-for="item of itemList" :key="item">
{{ item }}
</li>
</ul>
<Message
v-if="hint"
class="mt-2"
icon="pi pi-info-circle"
severity="secondary"
size="small"
variant="simple"
>
{{ hint }}
</Message>
</div>
<div class="flex shrink-0 flex-wrap justify-end gap-4">
<div
v-if="type === 'overwriteBlueprint'"
class="flex justify-start gap-4"
Expand Down Expand Up @@ -128,9 +133,3 @@ const onConfirm = () => {
useDialogStore().closeDialog()
}
</script>

<style lang="css" scoped>
.prompt-dialog-content {
white-space: pre-wrap;
}
</style>
Loading