Skip to content

Commit

Permalink
Subscription and payment blocks: improve loading animation (#38174)
Browse files Browse the repository at this point in the history
  • Loading branch information
simison authored Jul 5, 2024
1 parent 6e9ff5d commit 21c3e00
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: enhancement

Subscribe block: improve loading animation
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 18 additions & 2 deletions projects/plugins/jetpack/extensions/blocks/subscriptions/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import './view.scss';
import '../../shared/memberships.scss';

import domReady from '@wordpress/dom-ready';
import { showModal } from '../../shared/memberships';
import { showModal, spinner } from '../../shared/memberships';

// @ts-ignore
function show_iframe_retrieve_subscriptions_from_email() {
Expand Down Expand Up @@ -33,7 +33,7 @@ function show_iframe( data ) {

const url = 'https://subscribe.wordpress.com/memberships/?' + params.toString();

showModal( url );
return showModal( url );
}

domReady( function () {
Expand All @@ -49,11 +49,21 @@ domReady( function () {
forms.forEach( form => {
if ( ! form.payments_attached ) {
form.payments_attached = true;

const button = form.querySelector( 'button[type="submit"]' );

// Injects loading animation in hidden state
button.insertAdjacentHTML( 'beforeend', spinner );

form.addEventListener( 'submit', function ( event ) {
if ( form.resubmitted ) {
return;
}

button.classList.add( 'is-loading' );
button.setAttribute( 'aria-busy', 'true' );
button.setAttribute( 'aria-live', 'polite' );

// If email is empty, we will ask for it in the modal that opens
// Email input can be hidden for "button only style" for example.
let email = form.querySelector( 'input[type=email]' )?.value ?? '';
Expand Down Expand Up @@ -83,6 +93,12 @@ domReady( function () {
app_source,
post_access_level: form.dataset.post_access_level,
display: 'alternate',
} ).then( () => {
// Allows hiding other modals when the subscription modal/iframe shows up, e.g. hiding the subscription overlay modal
form.dispatchEvent( new Event( 'subscription-modal-loaded' ) );

button.classList.remove( 'is-loading' );
button.setAttribute( 'aria-busy', 'false' );
} );
}
} );
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
@import '@automattic/jetpack-base-styles/gutenberg-base-styles';

@function x($var-name, $fallback) {
@return unquote("var(#{$var-name}, #{$fallback})");
}


.is-style-compact {
.is-not-subscriber {
.wp-block-jetpack-subscriptions__button,
Expand Down
90 changes: 58 additions & 32 deletions projects/plugins/jetpack/extensions/shared/memberships.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,53 +22,79 @@ export function handleIframeResult( eventFromIframe ) {
window.removeEventListener( 'message', handleIframeResult );
const dialog = document.getElementById( 'memberships-modal-window' );
dialog.close();
document.body.classList.remove( 'modal-open' );
document.body.classList.remove( 'jetpack-memberships-modal-open' );
}
}
}

export function showModal( url ) {
// prevent double scroll bars. We use the entire viewport for the modal so we need to hide overflow on the body element.
document.body.classList.add( 'modal-open' );
return new Promise( resolvePromise => {
const existingModal = document.getElementById( 'memberships-modal-window' );
if ( existingModal ) {
document.body.removeChild( existingModal );
}

const existingModal = document.getElementById( 'memberships-modal-window' );
if ( existingModal ) {
document.body.removeChild( existingModal );
}
const dialog = document.createElement( 'dialog' );
dialog.setAttribute( 'id', 'memberships-modal-window' );
dialog.classList.add( 'jetpack-memberships-modal' );
dialog.classList.add( 'is-loading' );

const dialog = document.createElement( 'dialog' );
dialog.setAttribute( 'id', 'memberships-modal-window' );
const iframe = document.createElement( 'iframe' );
iframe.setAttribute( 'frameborder', '0' );
iframe.setAttribute( 'allowtransparency', 'true' );
iframe.setAttribute( 'allowfullscreen', 'true' );

const iframe = document.createElement( 'iframe' );
const inputLanguage = document.querySelector( 'input[name="lang"]' );
let siteLanguage = null;
if ( inputLanguage ) {
siteLanguage = inputLanguage.value;
}
iframe.setAttribute( 'id', 'memberships-modal-iframe' );
iframe.innerText =
'This feature requires inline frames. You have iframes disabled or your browser does not support them.';
iframe.src = url + '&display=alternate&jwt_token=' + getTokenFromCookie();
if ( siteLanguage ) {
iframe.src = iframe.src + '&lang=' + siteLanguage;
}
iframe.setAttribute( 'frameborder', '0' );
iframe.setAttribute( 'allowtransparency', 'true' );
iframe.setAttribute( 'allowfullscreen', 'true' );
dialog.classList.add( 'jetpack-memberships-modal' );
iframe.addEventListener( 'load', function () {
// prevent double scroll bars. We use the entire viewport for the modal so we need to hide overflow on the body element.
document.body.classList.add( 'jetpack-memberships-modal-open' );
dialog.classList.remove( 'is-loading' );
resolvePromise();
} );

iframe.setAttribute( 'id', 'memberships-modal-iframe' );
iframe.innerText =
'This feature requires inline frames. You have iframes disabled or your browser does not support them.';
iframe.src = url + '&display=alternate&jwt_token=' + getTokenFromCookie();

document.body.appendChild( dialog );
dialog.appendChild( iframe );
const siteLanguage = document.querySelector( 'input[name="lang"]' )?.value;
if ( siteLanguage ) {
iframe.src = iframe.src + '&lang=' + siteLanguage;
}
document.body.appendChild( dialog );
dialog.appendChild( iframe );

window.addEventListener( 'message', handleIframeResult, false );
dialog.showModal();
window.addEventListener( 'message', handleIframeResult, false );
dialog.showModal();
} );
}

export const spinner =
'<span class="jetpack-memberships-spinner">' +
' <svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
' <path d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z" opacity=".25" fill="currentColor" />' +
' <path d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z" class="jetpack-memberships-spinner-rotating" fill="currentColor" />' +
' </svg>' +
'</span>';

function setUpModal( button ) {
// Injects loading animation in hidden state
button.insertAdjacentHTML( 'beforeend', spinner );

button.addEventListener( 'click', event => {
event.preventDefault();
showModal( button.getAttribute( 'href' ) );
this.blur();

// Shows the injected loading animation in button
button.classList.add( 'is-loading' );
button.setAttribute( 'aria-busy', 'true' );
button.setAttribute( 'aria-live', 'polite' );

const url = button.getAttribute( 'href' );
showModal( url ).then( () => {
button.classList.remove( 'is-loading' );
button.setAttribute( 'aria-busy', 'false' );
} );

button.blur();
return false;
} );
}
Expand Down
90 changes: 53 additions & 37 deletions projects/plugins/jetpack/extensions/shared/memberships.scss
Original file line number Diff line number Diff line change
@@ -1,51 +1,67 @@
/* Additional styling to thickbox that displays modal */
/* stylelint-disable selector-max-id */
@import '@automattic/jetpack-base-styles/gutenberg-base-styles';

.jetpack-memberships-modal #TB_title {
display: none;
@keyframes jetpack-memberships_button__spinner-animation {
100% {
transform: rotate(360deg);
}
}

#memberships-modal-window.jetpack-memberships-modal,
#TB_window.jetpack-memberships-modal {
background-color: transparent;
background-image: url( 'https://s0.wp.com/i/loading/dark-200.gif' );
background-size: 50px;
background-repeat: no-repeat;
background-position: center 150px;
margin: 0 !important;
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
border: none;
bottom: 0;
left: 0;
right: 0;
top: 0;
width: 100% !important;
height: 100%;
.jetpack-memberships-spinner {
display: none;
width: 1em;
height: 1em;
margin: 0 0 0 5px;
svg {
/* Better center-align the spinner with button text, because 1m height doesn't take line-height into account */
margin-bottom: -2px;
width: 100%;
height: 100%;
}
}

#memberships-modal-window.jetpack-memberships-modal {
padding: 21px;
.jetpack-memberships-spinner-rotating {
transform-origin: center;
animation: jetpack-memberships_button__spinner-animation .75s infinite linear
}

.jetpack-memberships-modal #TB_iframeContent,
.jetpack-memberships-modal #memberships-modal-iframe {
margin: 0 !important;
height: 100% !important;
width: 100% !important;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
.is-loading .jetpack-memberships-spinner {
display: inline-block;
}
/* This is a class added by Thickbox on open modals. */
BODY.modal-open {

body.jetpack-memberships-modal-open {
overflow: hidden;
}

dialog::backdrop {
background-color: #000;
opacity: 0.7;
dialog.jetpack-memberships-modal {
opacity: 1;

&, iframe {
position: fixed;
margin: 0;
padding: 0;
height: 100%;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
box-shadow: none;
border: 0;
background: transparent;
}

&::backdrop {
background-color: #000;
opacity: 0.7;
transition: opacity .2s ease-out;
}

&.is-loading {
&, &::backdrop {
opacity: 0;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ domReady( function () {
return;
}

const close = document.getElementsByClassName( 'jetpack-subscribe-modal__close' )[ 0 ];
let hasLoaded = false;
let isScrolling;

Expand All @@ -25,7 +24,14 @@ domReady( function () {
}, Jetpack_Subscriptions.modalLoadTime );
};

// When the form is submitted, and next modal loads, it'll fire "subscription-modal-loaded" signalling that this form can be hidden.
const form = modal.querySelector( 'form' );
if ( form ) {
form.addEventListener( 'subscription-modal-loaded', closeModal );
}

// User can edit modal, and could remove close link.
const close = document.getElementsByClassName( 'jetpack-subscribe-modal__close' )[ 0 ];
if ( close ) {
close.onclick = function ( event ) {
event.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ domReady( function () {
return;
}

const close = document.querySelector( '.jetpack-subscribe-overlay__close' );
const close = overlay.querySelector( '.jetpack-subscribe-overlay__close' );
close.onclick = function ( event ) {
event.preventDefault();
closeOverlay();
};

const toContent = document.querySelector( '.jetpack-subscribe-overlay__to-content' );
const toContent = overlay.querySelector( '.jetpack-subscribe-overlay__to-content' );
// User can edit overlay, and could remove to content link.
if ( toContent ) {
toContent.onclick = function ( event ) {
Expand All @@ -25,9 +25,10 @@ domReady( function () {
};
}

const form = document.querySelector( '.jetpack-subscribe-overlay form' );
// When the form is submitted, and next modal loads, it'll fire "subscription-modal-loaded" signalling that this form can be hidden.
const form = overlay.querySelector( 'form' );
if ( form ) {
form.addEventListener( 'submit', closeOverlay );
form.addEventListener( 'subscription-modal-loaded', closeOverlay );
}

function closeOverlayOnEscapeKeydown( event ) {
Expand Down

0 comments on commit 21c3e00

Please sign in to comment.