Skip to content

Commit 4be7cf8

Browse files
authored
Merge pull request #90 from michaelchadwick/show-wrapped-modal
Show temporary notification when wrapping top <-> bottom in lightbox
2 parents 5df898c + ea96abe commit 4be7cf8

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

screenshot-tests/report.test.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,86 @@ test('each image click', async ({ page, browserName }) => {
4444
});
4545
}
4646
});
47+
48+
test('cycle images in row on left/right keyboard input', async ({ page }) => {
49+
await page.goto(reportUrl);
50+
51+
await page.locator('.diff-images button').first().click();
52+
await expect(page.locator('dialog#lightbox')).toBeVisible();
53+
54+
const firstImageCounter = page.locator('.lightbox-image-counter').first();
55+
56+
await expect(firstImageCounter).toHaveText('Image 1 / 3');
57+
58+
await page.keyboard.press('ArrowRight');
59+
await expect(firstImageCounter).toHaveText('Image 2 / 3');
60+
61+
await page.keyboard.press('ArrowRight');
62+
await expect(firstImageCounter).toHaveText('Image 3 / 3');
63+
64+
await page.keyboard.press('ArrowRight');
65+
await expect(firstImageCounter).toHaveText('Image 1 / 3');
66+
67+
await page.keyboard.press('ArrowLeft');
68+
await expect(firstImageCounter).toHaveText('Image 3 / 3');
69+
70+
await page.keyboard.press('ArrowLeft');
71+
await expect(firstImageCounter).toHaveText('Image 2 / 3');
72+
73+
await page.keyboard.press('ArrowLeft');
74+
await expect(firstImageCounter).toHaveText('Image 1 / 3');
75+
});
76+
77+
test('cycle rows on up/down keyboard input', async ({ page }) => {
78+
await page.goto(reportUrl);
79+
80+
await page.locator('.diff-images button').first().click();
81+
await expect(page.locator('dialog#lightbox')).toBeVisible();
82+
83+
const firstRowCounter = page.locator('.lightbox-row-counter').first();
84+
85+
await expect(firstRowCounter).toHaveText('Row 1 / 4');
86+
87+
await page.keyboard.press('ArrowDown');
88+
await expect(firstRowCounter).toHaveText('Row 2 / 4');
89+
90+
await page.keyboard.press('ArrowDown');
91+
await expect(firstRowCounter).toHaveText('Row 3 / 4');
92+
93+
await page.keyboard.press('ArrowDown');
94+
await expect(firstRowCounter).toHaveText('Row 4 / 4');
95+
96+
await page.keyboard.press('ArrowDown');
97+
await expect(firstRowCounter).toHaveText('Row 1 / 4');
98+
99+
await page.keyboard.press('ArrowUp');
100+
await expect(firstRowCounter).toHaveText('Row 4 / 4');
101+
102+
await page.keyboard.press('ArrowUp');
103+
await expect(firstRowCounter).toHaveText('Row 3 / 4');
104+
105+
await page.keyboard.press('ArrowUp');
106+
await expect(firstRowCounter).toHaveText('Row 2 / 4');
107+
108+
await page.keyboard.press('ArrowUp');
109+
await expect(firstRowCounter).toHaveText('Row 1 / 4');
110+
});
111+
112+
test('show temporary modals when wrapping top <-> bottom', async ({ page }) => {
113+
await page.goto(reportUrl);
114+
115+
await page.locator('.diff-images button').first().click();
116+
await expect(page.locator('dialog#lightbox')).toBeVisible();
117+
118+
const firstRowCounter = page.locator('.lightbox-row-counter').first();
119+
120+
await expect(firstRowCounter).toHaveText('Row 1 / 4');
121+
122+
await page.keyboard.press('ArrowUp');
123+
await expect(firstRowCounter).toHaveText('Row 4 / 4');
124+
await expect(page.getByRole('dialog').filter({ hasText: /^Wrapped to bottom$/ })).toBeVisible();
125+
126+
await page.keyboard.press('ArrowDown');
127+
await expect(firstRowCounter).toHaveText('Row 1 / 4');
128+
await expect(page.getByRole('dialog').filter({ hasText: /^Wrapped to top$/ })).toBeVisible();
129+
});

templates/report.html

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
}
4444

4545
#lightbox {
46+
z-index: 1;
47+
4648
&[open] {
4749
position: fixed;
4850
inset: 0;
@@ -192,6 +194,45 @@
192194
stroke-linecap: round;
193195
stroke-linejoin: round;
194196
}
197+
198+
#modal-window {
199+
background-color: #000;
200+
border: 2px solid #fff;
201+
border-radius: 8px;
202+
color: #fff;
203+
display: flex;
204+
justify-self: center;
205+
margin: 0 auto;
206+
max-height: 95%;
207+
max-width: 500px;
208+
opacity: 0;
209+
padding: 0;
210+
position: fixed;
211+
top: 20px;
212+
width: fit-content;
213+
214+
&.load {
215+
opacity: 1;
216+
transition: opacity 200ms ease-in-out;
217+
}
218+
219+
&.remove {
220+
opacity: 0;
221+
transition: opacity 500ms ease-in-out;
222+
}
223+
224+
.modal-text {
225+
display: flex;
226+
flex-direction: column;
227+
gap: 0.5em;
228+
justify-content: center;
229+
line-height: 1.1;
230+
margin: 0;
231+
overflow-y: auto;
232+
padding: 10px 5px;
233+
width: 100%;
234+
}
235+
}
195236
</style>
196237
</head>
197238
<body>
@@ -302,6 +343,63 @@ <h2>Missing or New Files</h2>
302343
</dialog>
303344

304345
<script>
346+
class Modal {
347+
constructor(modalText) {
348+
this.modalDelay = 1500;
349+
this.modalText = modalText;
350+
this.parent = document.getElementById('lightbox');
351+
352+
this.modal = null;
353+
this._createModal();
354+
355+
let modal = this;
356+
setTimeout(
357+
function (modal) {
358+
modal._destroyModal(false);
359+
}.bind(this, modal),
360+
this.modalDelay,
361+
);
362+
}
363+
364+
_createModal() {
365+
this.modal = document.createElement('dialog');
366+
this.modal.id = 'modal-window';
367+
368+
const text = document.createElement('div');
369+
text.classList.add('modal-text');
370+
text.innerHTML = this.modalText;
371+
this.modal.appendChild(text);
372+
373+
this.parent.appendChild(this.modal);
374+
375+
setTimeout(() => this.modal.classList.add('load'), 1);
376+
}
377+
378+
_destroyModal(immediate = false) {
379+
if (this.modal) {
380+
const modal = document.getElementById('modal-window');
381+
382+
if (this.parent.contains(modal)) {
383+
// remove modal immediately
384+
if (immediate) {
385+
this.parent.removeChild(modal);
386+
delete this;
387+
}
388+
// fade out modal gently
389+
else {
390+
this.modal.classList.remove('load');
391+
this.modal.classList.add('remove');
392+
393+
this.modal.addEventListener('transitionend', () => {
394+
this.parent.removeChild(modal);
395+
delete this;
396+
});
397+
}
398+
}
399+
}
400+
}
401+
}
402+
305403
(() => {
306404
const lightbox = document.querySelector('#lightbox');
307405
const filename = lightbox.querySelector('.lightbox-image-filename');
@@ -368,12 +466,24 @@ <h2>Missing or New Files</h2>
368466
event.preventDefault();
369467
const upRow = wrapRow(row - 1);
370468
show(upRow, Math.min(col, grid[upRow].length - 1));
469+
if (upRow == grid[upRow].length) {
470+
if (window.tempModal) {
471+
window.tempModal._destroyModal();
472+
}
473+
window.tempModal = new Modal('Wrapped to bottom');
474+
}
371475
break;
372476
}
373477
case 'ArrowDown': {
374478
event.preventDefault();
375479
const downRow = wrapRow(row + 1);
376480
show(downRow, Math.min(col, grid[downRow].length - 1));
481+
if (downRow == 0) {
482+
if (window.tempModal) {
483+
window.tempModal._destroyModal();
484+
}
485+
window.tempModal = new Modal('Wrapped to top');
486+
}
377487
break;
378488
}
379489
}

0 commit comments

Comments
 (0)