fix: align run controls with queue modal design (#9134)

## Summary
- move queue batch controls to the left of the run button
- align run control styling to the Figma queue modal spec using PrimeVue
PT/Tailwind (secondary background on batch + dropdown, primary run
button)
- normalize control heights to match actionbar buttons and tighten
dropdown hit area
- update run typography/spacing and replace all three chevrons (dropdown
+ batch up/down) with the requested SVG

Design:
https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3845-23904&m=dev

<img width="303" height="122" alt="image"
src="https://github.com/user-attachments/assets/4ed80ee7-3ceb-4512-96ce-f55ec6da835e"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9134-fix-align-run-controls-with-queue-modal-design-3106d73d36508160afcedbcfe4b98291)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Benjamin Lu
2026-03-06 20:10:59 -08:00
committed by GitHub
parent f02adf84eb
commit 1ada6dbfc6
45 changed files with 439 additions and 201 deletions

View File

@@ -1,7 +1,7 @@
import { createTestingPinia } from '@pinia/testing'
import { mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
import { defineComponent, nextTick } from 'vue'
import { nextTick } from 'vue'
import { createI18n } from 'vue-i18n'
import type {
@@ -41,28 +41,9 @@ vi.mock('@/stores/workspaceStore', () => ({
})
}))
const SplitButtonStub = defineComponent({
name: 'SplitButton',
props: {
label: {
type: String,
default: ''
},
severity: {
type: String,
default: 'primary'
}
},
template: `
<button
data-testid="split-button"
:data-label="label"
:data-severity="severity"
>
<slot name="icon" />
</button>
`
})
const BatchCountEditStub = {
template: '<div data-testid="batch-count-edit" />'
}
const i18n = createI18n({
legacy: false,
@@ -107,14 +88,26 @@ function createWrapper() {
tooltip: () => {}
},
stubs: {
SplitButton: SplitButtonStub,
BatchCountEdit: true
BatchCountEdit: BatchCountEditStub,
DropdownMenuRoot: { template: '<div><slot /></div>' },
DropdownMenuTrigger: { template: '<div><slot /></div>' },
DropdownMenuPortal: { template: '<div><slot /></div>' },
DropdownMenuContent: { template: '<div><slot /></div>' },
DropdownMenuItem: { template: '<div><slot /></div>' }
}
}
})
}
describe('ComfyQueueButton', () => {
it('renders the batch count control before the run button', () => {
const wrapper = createWrapper()
const controls = wrapper.get('.queue-button-group').element.children
expect(controls[0]?.getAttribute('data-testid')).toBe('batch-count-edit')
expect(controls[1]?.getAttribute('data-testid')).toBe('queue-button')
})
it('keeps the run instant presentation while idle even with active jobs', async () => {
const wrapper = createWrapper()
const queueSettingsStore = useQueueSettingsStore()
@@ -124,10 +117,10 @@ describe('ComfyQueueButton', () => {
queueStore.runningTasks = [createTask('run-1', 'in_progress')]
await nextTick()
const splitButton = wrapper.get('[data-testid="queue-button"]')
const queueButton = wrapper.get('[data-testid="queue-button"]')
expect(splitButton.attributes('data-label')).toBe('Run (Instant)')
expect(splitButton.attributes('data-severity')).toBe('primary')
expect(queueButton.text()).toContain('Run (Instant)')
expect(queueButton.attributes('data-variant')).toBe('primary')
expect(wrapper.find('.icon-\\[lucide--fast-forward\\]').exists()).toBe(true)
})
@@ -138,10 +131,10 @@ describe('ComfyQueueButton', () => {
queueSettingsStore.mode = 'instant-running'
await nextTick()
const splitButton = wrapper.get('[data-testid="queue-button"]')
const queueButton = wrapper.get('[data-testid="queue-button"]')
expect(splitButton.attributes('data-label')).toBe('Stop Run (Instant)')
expect(splitButton.attributes('data-severity')).toBe('danger')
expect(queueButton.text()).toContain('Stop Run (Instant)')
expect(queueButton.attributes('data-variant')).toBe('destructive')
expect(wrapper.find('.icon-\\[lucide--square\\]').exists()).toBe(true)
})
@@ -159,19 +152,17 @@ describe('ComfyQueueButton', () => {
await nextTick()
expect(queueSettingsStore.mode).toBe('instant-idle')
const splitButtonWhileStopping = wrapper.get('[data-testid="queue-button"]')
expect(splitButtonWhileStopping.attributes('data-label')).toBe(
'Run (Instant)'
)
expect(splitButtonWhileStopping.attributes('data-severity')).toBe('primary')
const queueButtonWhileStopping = wrapper.get('[data-testid="queue-button"]')
expect(queueButtonWhileStopping.text()).toContain('Run (Instant)')
expect(queueButtonWhileStopping.attributes('data-variant')).toBe('primary')
expect(wrapper.find('.icon-\\[lucide--fast-forward\\]').exists()).toBe(true)
expect(commandStore.execute).not.toHaveBeenCalled()
const splitButton = wrapper.get('[data-testid="queue-button"]')
const queueButton = wrapper.get('[data-testid="queue-button"]')
expect(queueSettingsStore.mode).toBe('instant-idle')
expect(splitButton.attributes('data-label')).toBe('Run (Instant)')
expect(splitButton.attributes('data-severity')).toBe('primary')
expect(queueButton.text()).toContain('Run (Instant)')
expect(queueButton.attributes('data-variant')).toBe('primary')
expect(wrapper.find('.icon-\\[lucide--fast-forward\\]').exists()).toBe(true)
})