Skip to content
51 changes: 48 additions & 3 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 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,15 @@ 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(
() =>
`${activeJobsCount.value} ${t('sideToolbar.queueProgressOverlay.activeJobsSuffix')}`
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: might want to create parameterized locale key and also localize the number

Copy link
Contributor

Choose a reason for hiding this comment

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

Also "jobs" vs. "job" can be done with i18n utilities.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

done with localized number and pluralized

)

const toast = useToast()

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

const handleClearQueue = async () => {
if (queuedCount.value === 0) return
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Shouldn't this guard be represented in the button state rather than the handler? If you can click this when queuedCount is 0, it means the button is not properly disabled.

Copy link
Member Author

Choose a reason for hiding this comment

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

removed if (queuedCount.value === 0) return

await commandStore.execute('Comfy.ClearPendingTasks')
}

const handleApproachEnd = useDebounceFn(async () => {
if (
activeTab.value === 'output' &&
Expand Down