Skip to content

Commit 666322e

Browse files
committed
Fix email opt-in modal reflow at high zoom (#1779)
1 parent d733aa9 commit 666322e

3 files changed

Lines changed: 79 additions & 1 deletion

File tree

src/emailOptIn/modal.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ import { createFocusTrap } from 'focus-trap';
1111
// Ensure the global variable is defined.
1212
window.edac_email_opt_in_form = window.edac_email_opt_in_form || {};
1313

14+
const getOptInModal = () => {
15+
const modal = document.getElementById( 'TB_window' );
16+
modal?.classList.add( 'edac-email-opt-in-modal' );
17+
18+
return modal;
19+
};
20+
1421
export const initOptInModal = () => {
1522
window.addEventListener( 'load', () => {
1623
window.addEventListener( 'mousemove', triggerModal, { once: true } );
@@ -28,6 +35,7 @@ const triggerModal = ( () => {
2835
hasRun = true;
2936

3037
tb_show( 'Accessibility Checker', '#TB_inline?width=600&inlineId=edac-opt-in-modal', null );
38+
getOptInModal();
3139

3240
// Loop and check for the close button before trying to bind the focus trap.
3341
let attempts = 0;
@@ -49,7 +57,7 @@ const triggerModal = ( () => {
4957
} )();
5058

5159
const bindFocusTrap = () => {
52-
const modal = document.getElementById( 'TB_window' );
60+
const modal = getOptInModal();
5361
const closeIcon = modal?.querySelector( '.tb-close-icon' );
5462
if ( ! modal || ! closeIcon ) {
5563
return false;

src/emailOptIn/sass/email-opt-in.scss

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
padding: 0;
33
margin: 0;
44
input {
5+
box-sizing: border-box;
56
width: 100%;
67
}
78

@@ -23,4 +24,32 @@
2324
}
2425
}
2526

27+
#TB_window.edac-email-opt-in-modal {
28+
box-sizing: border-box;
29+
width: calc(100vw - 2rem) !important;
30+
max-width: 630px;
31+
max-height: calc(100vh - 2rem);
32+
margin: 0 !important;
33+
transform: translate(-50%, -50%);
34+
35+
#TB_ajaxContent {
36+
box-sizing: border-box;
37+
width: 100% !important;
38+
height: auto !important;
39+
max-height: calc(100vh - 4rem) !important;
40+
overflow-y: auto;
41+
}
42+
}
43+
44+
@media screen and (max-width: 600px) {
45+
#TB_window.edac-email-opt-in-modal #_form_1_ ._button-wrapper {
46+
flex-direction: column;
47+
align-items: stretch;
48+
49+
button {
50+
width: 100%;
51+
}
52+
}
53+
}
54+
2655

tests/jest/emailOptIn/modal.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Tests for email opt-in modal initialization
33
*/
44

5+
import { createFocusTrap } from 'focus-trap';
56
import { initOptInModal } from '../../../src/emailOptIn/modal';
67

78
jest.mock(
@@ -15,9 +16,18 @@ jest.mock(
1516
describe( 'email opt-in modal init', () => {
1617
beforeEach( () => {
1718
jest.restoreAllMocks();
19+
jest.useRealTimers();
20+
document.body.innerHTML = '';
1821
window.onload = null;
1922
} );
2023

24+
afterEach( () => {
25+
jest.clearAllTimers();
26+
jest.useRealTimers();
27+
delete window.tb_show;
28+
delete window.jQuery;
29+
} );
30+
2131
test( 'does not overwrite existing window.onload handler', () => {
2232
const existingOnload = jest.fn();
2333
window.onload = existingOnload;
@@ -43,4 +53,35 @@ describe( 'email opt-in modal init', () => {
4353
expect( addEventListenerSpy ).toHaveBeenCalledWith( 'mousemove', expect.any( Function ), { once: true } );
4454
expect( addEventListenerSpy ).toHaveBeenCalledWith( 'scroll', expect.any( Function ), { once: true } );
4555
} );
56+
57+
test( 'marks the email opt-in ThickBox before activating its focus trap', () => {
58+
jest.useFakeTimers();
59+
60+
const modal = document.createElement( 'div' );
61+
modal.id = 'TB_window';
62+
modal.innerHTML = '<button class="tb-close-icon">Close</button>';
63+
64+
const focusTrap = {
65+
activate: jest.fn(),
66+
deactivate: jest.fn(),
67+
};
68+
createFocusTrap.mockReturnValue( focusTrap );
69+
window.tb_show = jest.fn( () => document.body.appendChild( modal ) );
70+
window.jQuery = jest.fn( () => ( { one: jest.fn() } ) );
71+
72+
const addEventListenerSpy = jest.spyOn( window, 'addEventListener' );
73+
initOptInModal();
74+
75+
const loadCall = addEventListenerSpy.mock.calls.find( ( call ) => call[ 0 ] === 'load' );
76+
loadCall[ 1 ]();
77+
const mousemoveCall = addEventListenerSpy.mock.calls.find( ( call ) => call[ 0 ] === 'mousemove' );
78+
mousemoveCall[ 1 ]();
79+
80+
expect( modal.classList.contains( 'edac-email-opt-in-modal' ) ).toBe( true );
81+
82+
jest.advanceTimersByTime( 250 );
83+
84+
expect( createFocusTrap ).toHaveBeenCalledWith( modal );
85+
expect( focusTrap.activate ).toHaveBeenCalled();
86+
} );
4687
} );

0 commit comments

Comments
 (0)