Files
ComfyUI_frontend/src/components/queue/QueueOverlayExpanded.vue
Benjamin Lu e70484d596 fix: move queue assets action into filter controls (#8926)
## Summary

Move the queue overlay "Show assets" action into the filter controls as
an icon button, so the action is available inline with other list
controls while keeping existing behavior.

## Changes

- **What**:
- Remove the full-width "Show assets" button from
`QueueOverlayExpanded`.
- Add a secondary icon button in `JobFiltersBar` with tooltip +
aria-label and emit `showAssets` on click.
- Wire `showAssets` from `JobFiltersBar` through `QueueOverlayExpanded`
to the existing handler.
- Add `JobFiltersBar` unit coverage to verify `showAssets` is emitted
when the icon button is clicked.

## Review Focus

- Verify the icon button placement in the filter row is sensible and
discoverable.
- Verify clicking the new button opens the assets panel as before.
- Verify tooltip and accessibility label copy are correct.

## Screenshots (if applicable)
Design:
https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3924-38560&m=dev
<img width="349" height="52" alt="Screenshot 2026-02-16 at 4 53 34 PM"
src="https://github.com/user-attachments/assets/347772d6-5536-457a-a65f-de251e35a0e4"
/>
2026-02-16 18:19:16 -08:00

111 lines
3.2 KiB
Vue

<template>
<div class="flex w-full flex-col gap-4">
<QueueOverlayHeader
:header-title="headerTitle"
:show-concurrent-indicator="showConcurrentIndicator"
:concurrent-workflow-count="concurrentWorkflowCount"
:queued-count="queuedCount"
@clear-history="$emit('clearHistory')"
@clear-queued="$emit('clearQueued')"
/>
<JobFiltersBar
:selected-job-tab="selectedJobTab"
:selected-workflow-filter="selectedWorkflowFilter"
:selected-sort-mode="selectedSortMode"
:has-failed-jobs="hasFailedJobs"
@show-assets="$emit('showAssets')"
@update:selected-job-tab="$emit('update:selectedJobTab', $event)"
@update:selected-workflow-filter="
$emit('update:selectedWorkflowFilter', $event)
"
@update:selected-sort-mode="$emit('update:selectedSortMode', $event)"
/>
<div class="flex-1 min-h-0 overflow-y-auto">
<JobGroupsList
:displayed-job-groups="displayedJobGroups"
@cancel-item="onCancelItemEvent"
@delete-item="onDeleteItemEvent"
@view-item="$emit('viewItem', $event)"
@menu="onMenuItem"
/>
</div>
<JobContextMenu
ref="jobContextMenuRef"
:entries="jobMenuEntries"
@action="onJobMenuAction"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type {
JobGroup,
JobListItem,
JobSortMode,
JobTab
} from '@/composables/queue/useJobList'
import type { MenuEntry } from '@/composables/queue/useJobMenu'
import { useJobMenu } from '@/composables/queue/useJobMenu'
import QueueOverlayHeader from './QueueOverlayHeader.vue'
import JobContextMenu from './job/JobContextMenu.vue'
import JobFiltersBar from './job/JobFiltersBar.vue'
import JobGroupsList from './job/JobGroupsList.vue'
defineProps<{
headerTitle: string
showConcurrentIndicator: boolean
concurrentWorkflowCount: number
queuedCount: number
selectedJobTab: JobTab
selectedWorkflowFilter: 'all' | 'current'
selectedSortMode: JobSortMode
displayedJobGroups: JobGroup[]
hasFailedJobs: boolean
}>()
const emit = defineEmits<{
(e: 'showAssets'): void
(e: 'clearHistory'): void
(e: 'clearQueued'): void
(e: 'update:selectedJobTab', value: JobTab): void
(e: 'update:selectedWorkflowFilter', value: 'all' | 'current'): void
(e: 'update:selectedSortMode', value: JobSortMode): void
(e: 'cancelItem', item: JobListItem): void
(e: 'deleteItem', item: JobListItem): void
(e: 'viewItem', item: JobListItem): void
}>()
const currentMenuItem = ref<JobListItem | null>(null)
const jobContextMenuRef = ref<InstanceType<typeof JobContextMenu> | null>(null)
const { jobMenuEntries } = useJobMenu(
() => currentMenuItem.value,
(item) => emit('viewItem', item)
)
const onCancelItemEvent = (item: JobListItem) => {
emit('cancelItem', item)
}
const onDeleteItemEvent = (item: JobListItem) => {
emit('deleteItem', item)
}
const onMenuItem = (item: JobListItem, event: Event) => {
currentMenuItem.value = item
jobContextMenuRef.value?.open(event)
}
const onJobMenuAction = async (entry: MenuEntry) => {
if (entry.kind === 'divider') return
if (entry.onClick) await entry.onClick()
jobContextMenuRef.value?.hide()
}
</script>