Skip to content
56 changes: 52 additions & 4 deletions src/components/sidebar/tabs/AssetsSidebarTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,31 @@
class="pb-1 px-2 2xl:px-4"
:show-generation-time-sort="activeTab === 'output'"
/>
<Divider type="dashed" class="my-2" />
<div
v-if="isQueuePanelV2Enabled"
class="flex items-center justify-between px-2 py-2 2xl:px-4"
>
<span class="text-sm text-muted-foreground">
{{ activeJobsLabel }}
</span>
<div class="flex items-center gap-2">
<span class="text-sm text-base-foreground">
{{ t('sideToolbar.queueProgressOverlay.clearQueueTooltip') }}
</span>
<Button
variant="destructive"
size="icon"
:aria-label="
t('sideToolbar.queueProgressOverlay.clearQueueTooltip')
"
Comment on lines +63 to +71
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

Remove redundant aria-label from button with visible text.

The button displays visible text "Clear queue" (lines 63-65), making the aria-label (lines 69-71) redundant. Per accessibility guidelines, visible text provides the accessible name.

Additionally, the translation key clearQueueTooltip suggests tooltip usage, but here it's rendered as visible text. Consider using a dedicated translation key for the visible label or confirming this matches the design intent.

🔎 Proposed fix
-          <span class="text-sm text-base-foreground">
-            {{ t('sideToolbar.queueProgressOverlay.clearQueueTooltip') }}
-          </span>
           <Button
             variant="destructive"
             size="icon"
-            :aria-label="
-              t('sideToolbar.queueProgressOverlay.clearQueueTooltip')
-            "
             :disabled="queuedCount === 0"
             @click="handleClearQueue"
           >
+            <span class="text-sm text-base-foreground">
+              {{ t('sideToolbar.queueProgressOverlay.clearQueue') }}
+            </span>
             <i class="icon-[lucide--list-x] size-4" />
           </Button>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @src/components/sidebar/tabs/AssetsSidebarTab.vue around lines 63 - 71, The
Button component currently has redundant accessible text because a visible span
(the "Clear queue" label rendered via
t('sideToolbar.queueProgressOverlay.clearQueueTooltip')) and an aria-label with
the same translation key are both used; remove the aria-label attribute from the
Button (or replace it with a dedicated label key if design requires a different
accessible name) and, if the visible text should be a separate translation
string, switch the span to use a label key (e.g.,
t('sideToolbar.queueProgressOverlay.clearQueueLabel')) while keeping
tooltip/localized tooltip text separate.

:disabled="queuedCount === 0"
@click="handleClearQueue"
>
<i class="icon-[lucide--list-x] size-4" />
</Button>
</div>
Comment on lines +63 to +77
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

Remove redundant aria-label on button with visible text.

The button displays visible text "Clear queue" (lines 63-65), so the aria-label (lines 69-71) is redundant and should be removed per accessibility guidelines. This duplicates a previous review comment.

🔎 Proposed fix
         <Button
           variant="destructive"
           size="icon"
-          :aria-label="
-            t('sideToolbar.queueProgressOverlay.clearQueueTooltip')
-          "
           :disabled="queuedCount === 0"
           @click="handleClearQueue"
         >
🤖 Prompt for AI Agents
In @src/components/sidebar/tabs/AssetsSidebarTab.vue around lines 63 - 77, The
Button rendering the "Clear queue" control currently includes a redundant
:aria-label binding using
t('sideToolbar.queueProgressOverlay.clearQueueTooltip'); remove the :aria-label
prop from the Button component (the element with @click="handleClearQueue" and
:disabled="queuedCount === 0") so the visible text span provides the accessible
name and no duplicate aria-label remains; keep the Button's variant/size,
disabled binding, and click handler intact.

</div>
<Divider v-else type="dashed" class="my-2" />
Comment on lines +55 to +79
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check Divider import and all imports in the file
echo "=== Checking imports in AssetsSidebarTab.vue ==="
rg -n "^import|^from" src/components/sidebar/tabs/AssetsSidebarTab.vue | head -30

echo -e "\n=== Checking if Divider is imported ==="
rg -n "Divider" src/components/sidebar/tabs/AssetsSidebarTab.vue

echo -e "\n=== Checking i18n keys in locale file ==="
rg -n "sideToolbar.queueProgressOverlay" src/locales/en/main.json

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2276


🏁 Script executed:

#!/bin/bash
# Get more context from the file to check activeJobsLabel and other refs
echo "=== Checking file structure and component setup ==="
head -50 src/components/sidebar/tabs/AssetsSidebarTab.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1805


🏁 Script executed:

#!/bin/bash
# Search for Divider component imports in other files to find correct source
echo "=== Where is Divider imported from in other files? ==="
rg -r "import.*Divider" --type vue src/ | head -10

# Check what i18n keys exist for queueProgressOverlay
echo -e "\n=== All queueProgressOverlay references in codebase ==="
rg "queueProgressOverlay" src/ --type vue --type json

# Get the exact lines 55-79 from the file
echo -e "\n=== Lines 55-79 of AssetsSidebarTab.vue ==="
sed -n '55,79p' src/components/sidebar/tabs/AssetsSidebarTab.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1150


🏁 Script executed:

#!/bin/bash
# Check the complete i18n file structure for queue/clear related keys
echo "=== Checking locale file for queue-related keys ==="
rg "queue|Queue" src/locales/en/main.json -i -B1 -A1 | head -50

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2028


🏁 Script executed:

#!/bin/bash
# Search for Divider component definition
echo "=== Searching for Divider component definition ==="
fd -e vue -e ts Divider src/ | head -20

# Check if there's a Divider in components/common or ui
ls -la src/components/ui/ 2>/dev/null | grep -i divider
ls -la src/components/common/ 2>/dev/null | grep -i divider

# Get the script section to find activeJobsLabel and other logic
echo -e "\n=== Getting script section (setup logic) ==="
sed -n '150,200p' src/components/sidebar/tabs/AssetsSidebarTab.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2448


🏁 Script executed:

#!/bin/bash
# Search for activeJobsLabel definition
echo "=== Searching for activeJobsLabel ==="
rg "activeJobsLabel" src/components/sidebar/tabs/AssetsSidebarTab.vue -B2 -A2

# Get full imports and script setup
echo -e "\n=== Full script section start ==="
sed -n '220,280p' src/components/sidebar/tabs/AssetsSidebarTab.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2427


Remove redundant aria-label and fix missing Divider import.

The button has visible text content (lines 63-65), so the aria-label attribute (lines 69-71) is redundant and violates accessibility best practices. Remove it—the visible text provides the accessible name.

Additionally, the Divider component at line 79 is used but never imported, which will cause a runtime error. Import Divider from PrimeVue or replace it with ContentDivider or TextDivider from @/components/common/.

Proposed fix for aria-label
         <Button
           variant="destructive"
           size="icon"
-          :aria-label="
-            t('sideToolbar.queueProgressOverlay.clearQueueTooltip')
-          "
           :disabled="queuedCount === 0"
           @click="handleClearQueue"
         >
📝 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
<div
v-if="isQueuePanelV2Enabled"
class="flex items-center justify-between px-2 py-2 2xl:px-4"
>
<span class="text-sm text-muted-foreground">
{{ activeJobsLabel }}
</span>
<div class="flex items-center gap-2">
<span class="text-sm text-base-foreground">
{{ t('sideToolbar.queueProgressOverlay.clearQueueTooltip') }}
</span>
<Button
variant="destructive"
size="icon"
:aria-label="
t('sideToolbar.queueProgressOverlay.clearQueueTooltip')
"
:disabled="queuedCount === 0"
@click="handleClearQueue"
>
<i class="icon-[lucide--list-x] size-4" />
</Button>
</div>
</div>
<Divider v-else type="dashed" class="my-2" />
<div
v-if="isQueuePanelV2Enabled"
class="flex items-center justify-between px-2 py-2 2xl:px-4"
>
<span class="text-sm text-muted-foreground">
{{ activeJobsLabel }}
</span>
<div class="flex items-center gap-2">
<span class="text-sm text-base-foreground">
{{ t('sideToolbar.queueProgressOverlay.clearQueueTooltip') }}
</span>
<Button
variant="destructive"
size="icon"
:disabled="queuedCount === 0"
@click="handleClearQueue"
>
<i class="icon-[lucide--list-x] size-4" />
</Button>
</div>
</div>
<Divider v-else type="dashed" class="my-2" />
🤖 Prompt for AI Agents
In @src/components/sidebar/tabs/AssetsSidebarTab.vue around lines 55 - 79,
Remove the redundant aria-label prop on the Button (the visible span already
provides the accessible name) by deleting the
:aria-label="t('sideToolbar.queueProgressOverlay.clearQueueTooltip')" binding,
and ensure the Divider used in the template is properly imported/registered:
either import Divider from 'primevue/divider' and add it to the component's
components object, or replace the <Divider> with an existing local component
like ContentDivider or TextDivider from "@/components/common/" and
import/register that component; keep the existing conditional block and handlers
(isQueuePanelV2Enabled, handleClearQueue, queuedCount) unchanged.

</template>
<template #body>
<div v-if="loading && !displayAssets.length">
Expand Down Expand Up @@ -165,7 +189,6 @@

<script setup lang="ts">
import { useDebounceFn, useElementHover, useResizeObserver } from '@vueuse/core'
import { Divider } from 'primevue'
import ProgressSpinner from 'primevue/progressspinner'
import { useToast } from 'primevue/usetoast'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
Expand All @@ -188,18 +211,26 @@ import { useMediaAssetFiltering } from '@/platform/assets/composables/useMediaAs
import { getOutputAssetMetadata } from '@/platform/assets/schemas/assetMetadataSchema'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import { isCloud } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useCommandStore } from '@/stores/commandStore'
import { useDialogStore } from '@/stores/dialogStore'
import { ResultItemImpl } from '@/stores/queueStore'
import { ResultItemImpl, useQueueStore } from '@/stores/queueStore'
import { formatDuration, getMediaTypeFromFilename } from '@/utils/formatUtil'
import { cn } from '@/utils/tailwindUtil'

const { t } = useI18n()
const { t, n } = useI18n()
const commandStore = useCommandStore()
const queueStore = useQueueStore()
const settingStore = useSettingStore()

const activeTab = ref<'input' | 'output'>('output')
const folderPromptId = ref<string | null>(null)
const folderExecutionTime = ref<number | undefined>(undefined)
const isInFolderView = computed(() => folderPromptId.value !== null)
const viewMode = ref<'list' | 'grid'>('grid')
const isQueuePanelV2Enabled = computed(() =>
settingStore.get('Comfy.Queue.QPOV2')
)

// Track which asset's context menu is open (for single-instance context menu management)
const openContextMenuId = ref<string | null>(null)
Expand Down Expand Up @@ -228,6 +259,19 @@ const formattedExecutionTime = computed(() => {
return formatDuration(folderExecutionTime.value * 1000)
})

const queuedCount = computed(() => queueStore.pendingTasks.length)
const activeJobsCount = computed(
() => queueStore.pendingTasks.length + queueStore.runningTasks.length
)
const activeJobsLabel = computed(() => {
const count = activeJobsCount.value
return t(
'sideToolbar.queueProgressOverlay.activeJobs',
{ count: n(count) },
count
)
})
Comment on lines +267 to +274
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 | 🟠 Major

Fix incorrect vue-i18n pluralization pattern.

The activeJobsLabel computed property uses an incorrect three-parameter i18n pattern where n(count) (a formatted string) is passed as the count value. This breaks plural selection, which requires a raw numeric value.

The standard vue-i18n pluralization pattern uses two parameters: t('key', { count }) where the raw count triggers plural selection from pipe-separated locale strings.

🔎 Proposed fix
 const activeJobsLabel = computed(() => {
   const count = activeJobsCount.value
   return t(
     'sideToolbar.queueProgressOverlay.activeJobs',
-    { count: n(count) },
-    count
+    { count }
   )
 })

If formatted numbers are required in the display, update the locale string to:

"activeJobs": "{count, number} active job | {count, number} active jobs"

Based on learnings about vue-i18n pluralization patterns.

📝 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
const activeJobsLabel = computed(() => {
const count = activeJobsCount.value
return t(
'sideToolbar.queueProgressOverlay.activeJobs',
{ count: n(count) },
count
)
})
const activeJobsLabel = computed(() => {
const count = activeJobsCount.value
return t(
'sideToolbar.queueProgressOverlay.activeJobs',
{ count }
)
})
🤖 Prompt for AI Agents
In @src/components/sidebar/tabs/AssetsSidebarTab.vue around lines 267 - 274, The
pluralization call in the computed activeJobsLabel incorrectly passes n(count)
(a formatted string) as the count, breaking vue-i18n plural selection; change
the t invocation inside activeJobsLabel to pass the raw numeric
activeJobsCount.value as the count (e.g.,
t('sideToolbar.queueProgressOverlay.activeJobs', { count })) and, if you still
need formatted numbers, update the locale entry to use a number formatter (e.g.,
"{count, number} active job | {count, number} active jobs") or apply n(count)
only to the rendered output after plural selection.


const toast = useToast()

const inputAssets = useMediaAssets('input')
Expand Down Expand Up @@ -492,6 +536,10 @@ const handleDeleteSelected = async () => {
clearSelection()
}

const handleClearQueue = async () => {
await commandStore.execute('Comfy.ClearPendingTasks')
}

const handleApproachEnd = useDebounceFn(async () => {
if (
activeTab.value === 'output' &&
Expand Down
1 change: 1 addition & 0 deletions src/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@
"filterCurrentWorkflow": "Current workflow",
"sortJobs": "Sort jobs",
"sortBy": "Sort by",
"activeJobs": "{count} active job | {count} active jobs",
"activeJobsSuffix": "active jobs",
"jobQueue": "Job Queue",
"expandCollapsedQueue": "Expand job queue",
Expand Down