Skip to content

Commit 08a1fd0

Browse files
Dismiss gallery lightbox on background click (#752)
* Dismiss gallery on background click * Add vitest tests
1 parent 56f3842 commit 08a1fd0

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

src/components/sidebar/tabs/queue/ResultGallery.vue

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
fullScreen
1212
circular
1313
:showThumbnails="false"
14+
:pt="{
15+
mask: {
16+
onMousedown: onMaskMouseDown,
17+
onMouseup: onMaskMouseUp,
18+
'data-mask': true
19+
}
20+
}"
1421
>
1522
<template #item="{ item }">
1623
<ComfyImage
@@ -40,6 +47,24 @@ const props = defineProps<{
4047
activeIndex: number
4148
}>()
4249
50+
let maskMouseDownTarget: EventTarget | null = null
51+
52+
const onMaskMouseDown = (event: MouseEvent) => {
53+
maskMouseDownTarget = event.target
54+
}
55+
56+
const onMaskMouseUp = (event: MouseEvent) => {
57+
const maskEl = document.querySelector('[data-mask]')
58+
if (
59+
galleryVisible.value &&
60+
maskMouseDownTarget === event.target &&
61+
maskMouseDownTarget === maskEl
62+
) {
63+
galleryVisible.value = false
64+
handleVisibilityChange(false)
65+
}
66+
}
67+
4368
watch(
4469
() => props.activeIndex,
4570
(index) => {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { mount } from '@vue/test-utils'
2+
import { expect, describe, it } from 'vitest'
3+
import ResultGallery from '../ResultGallery.vue'
4+
import Galleria from 'primevue/galleria'
5+
import ComfyImage from '@/components/common/ComfyImage.vue'
6+
import PrimeVue from 'primevue/config'
7+
import { ResultItemImpl } from '@/stores/queueStore'
8+
9+
type ResultGalleryProps = typeof ResultGallery.__props
10+
11+
describe('ResultGallery', () => {
12+
let mockResultItem: ResultItemImpl
13+
14+
beforeEach(() => {
15+
mockResultItem = {
16+
filename: 'test.jpg',
17+
type: 'images',
18+
nodeId: 'test',
19+
mediaType: 'images',
20+
url: 'https://picsum.photos/200/300',
21+
urlWithTimestamp: 'https://picsum.photos/200/300?t=123456',
22+
supportsPreview: true
23+
}
24+
})
25+
26+
const mountResultGallery = (props: ResultGalleryProps, options = {}) => {
27+
return mount(ResultGallery, {
28+
global: {
29+
plugins: [PrimeVue],
30+
components: { Galleria, ComfyImage }
31+
},
32+
props,
33+
...options
34+
})
35+
}
36+
37+
const clickElement = async (element: Element) => {
38+
element.dispatchEvent(new MouseEvent('mousedown'))
39+
element.dispatchEvent(new MouseEvent('mouseup'))
40+
}
41+
42+
it('is dismissed when overlay mask is clicked', async () => {
43+
const wrapper = mountResultGallery({
44+
activeIndex: 0,
45+
allGalleryItems: [mockResultItem]
46+
})
47+
wrapper.vm.galleryVisible = true
48+
await wrapper.vm.$nextTick()
49+
expect(wrapper.findComponent(Galleria).exists()).toBe(true)
50+
expect(wrapper.vm.galleryVisible).toBe(true)
51+
52+
// Since Galleria uses teleport, we need to query the mask in the global document
53+
const mask = document.querySelector('[data-mask]')
54+
expect(mask).not.toBeNull()
55+
56+
// Click the overlay mask to dismiss the gallery
57+
await clickElement(mask)
58+
await wrapper.vm.$nextTick()
59+
expect(wrapper.vm.galleryVisible).toBe(false)
60+
})
61+
62+
it('is not dismissed when gallery is clicked', async () => {
63+
const wrapper = mountResultGallery({
64+
activeIndex: 0,
65+
allGalleryItems: [mockResultItem]
66+
})
67+
wrapper.vm.galleryVisible = true
68+
await wrapper.vm.$nextTick()
69+
expect(wrapper.findComponent(Galleria).exists()).toBe(true)
70+
expect(wrapper.vm.galleryVisible).toBe(true)
71+
72+
// Since Galleria uses teleport, we need to query the mask in the global document
73+
const gallery = document.querySelector('.p-galleria-content')
74+
expect(gallery).not.toBeNull()
75+
76+
// The gallery should not be dismissed when the gallery itself is clicked
77+
await clickElement(gallery)
78+
await wrapper.vm.$nextTick()
79+
expect(wrapper.vm.galleryVisible).toBe(true)
80+
})
81+
})

0 commit comments

Comments
 (0)