Skip to content

Commit f55d7b8

Browse files
committed
Refine Motion preview settled state
Refs #418
1 parent 322e0ce commit f55d7b8

File tree

8 files changed

+164
-44
lines changed

8 files changed

+164
-44
lines changed

dist/js/admin/customizer-motion-controls.js

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ module.exports = {
5454
(module) {
5555

5656
const PREVIEW_ROOT_ID = 'anima-motion-preview-root';
57-
const PREVIEW_HIDE_DELAY = 2200;
58-
const PREVIEW_FADE_OUT_DELAY = 180;
57+
const PREVIEW_SETTLE_DELAY = 1200;
5958
function escapeHtml(value) {
6059
return String(value).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
6160
}
@@ -80,11 +79,11 @@ function getOverlayMarkup(state, config) {
8079
return `<div class="c-page-transition-border c-page-transition-border--preview" style="border-color: var(--sm-current-accent-color); background: var(--sm-current-accent-color);">${loadingMarkup}</div>`;
8180
}
8281
function clearMotionPreviewTimer(previewWindow) {
83-
if (!previewWindow || !previewWindow.__animaMotionPreviewHideTimer) {
82+
if (!previewWindow || !previewWindow.__animaMotionPreviewSettleTimer) {
8483
return;
8584
}
86-
previewWindow.clearTimeout(previewWindow.__animaMotionPreviewHideTimer);
87-
previewWindow.__animaMotionPreviewHideTimer = null;
85+
previewWindow.clearTimeout(previewWindow.__animaMotionPreviewSettleTimer);
86+
previewWindow.__animaMotionPreviewSettleTimer = null;
8887
}
8988
function removeMotionPreview(previewDocument) {
9089
if (!previewDocument) {
@@ -96,22 +95,15 @@ function removeMotionPreview(previewDocument) {
9695
existingRoot.remove();
9796
}
9897
}
99-
function hideMotionPreview(previewDocument) {
98+
function settleMotionPreview(previewDocument) {
10099
if (!previewDocument) {
101100
return;
102101
}
103-
const previewWindow = previewDocument.defaultView;
104102
const existingRoot = previewDocument.getElementById(PREVIEW_ROOT_ID);
105-
if (!previewWindow || !existingRoot) {
103+
if (!existingRoot) {
106104
return;
107105
}
108-
existingRoot.classList.add('anima-motion-preview-root--hiding');
109-
previewWindow.setTimeout(() => {
110-
const currentRoot = previewDocument.getElementById(PREVIEW_ROOT_ID);
111-
if (currentRoot) {
112-
currentRoot.remove();
113-
}
114-
}, PREVIEW_FADE_OUT_DELAY);
106+
existingRoot.classList.add('anima-motion-preview-root--settled');
115107
}
116108
function renderMotionPreview(previewDocument, state, config = {}) {
117109
removeMotionPreview(previewDocument);
@@ -128,7 +120,7 @@ function renderMotionPreview(previewDocument, state, config = {}) {
128120
previewRoot.setAttribute('aria-hidden', 'true');
129121
previewRoot.innerHTML = getOverlayMarkup(state, config);
130122
previewDocument.body.appendChild(previewRoot);
131-
previewWindow.__animaMotionPreviewHideTimer = previewWindow.setTimeout(() => hideMotionPreview(previewDocument), config.previewDuration || PREVIEW_HIDE_DELAY);
123+
previewWindow.__animaMotionPreviewSettleTimer = previewWindow.setTimeout(() => settleMotionPreview(previewDocument), config.previewSettleDelay || PREVIEW_SETTLE_DELAY);
132124
}
133125
module.exports = {
134126
renderMotionPreview

dist/js/admin/customizer-motion-controls.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inc/admin/class-admin-customize.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function enqueue_assets() {
111111
[
112112
'fallbackSymbol' => anima_first_site_title_character(),
113113
'progressBarMarkup' => anima_get_loading_content_markup( 'progress_bar' ),
114-
'previewDuration' => 2200,
114+
'previewSettleDelay' => 1200,
115115
]
116116
);
117117
}

src/js/admin/customizer-motion-preview-dom.js

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const PREVIEW_ROOT_ID = 'anima-motion-preview-root';
2-
const PREVIEW_HIDE_DELAY = 2200;
3-
const PREVIEW_FADE_OUT_DELAY = 180;
2+
const PREVIEW_SETTLE_DELAY = 1200;
43

54
function escapeHtml(value) {
65
return String(value)
@@ -40,12 +39,12 @@ function getOverlayMarkup(state, config) {
4039
}
4140

4241
function clearMotionPreviewTimer(previewWindow) {
43-
if (!previewWindow || !previewWindow.__animaMotionPreviewHideTimer) {
42+
if (!previewWindow || !previewWindow.__animaMotionPreviewSettleTimer) {
4443
return;
4544
}
4645

47-
previewWindow.clearTimeout(previewWindow.__animaMotionPreviewHideTimer);
48-
previewWindow.__animaMotionPreviewHideTimer = null;
46+
previewWindow.clearTimeout(previewWindow.__animaMotionPreviewSettleTimer);
47+
previewWindow.__animaMotionPreviewSettleTimer = null;
4948
}
5049

5150
function removeMotionPreview(previewDocument) {
@@ -61,26 +60,18 @@ function removeMotionPreview(previewDocument) {
6160
}
6261
}
6362

64-
function hideMotionPreview(previewDocument) {
63+
function settleMotionPreview(previewDocument) {
6564
if (!previewDocument) {
6665
return;
6766
}
6867

69-
const previewWindow = previewDocument.defaultView;
7068
const existingRoot = previewDocument.getElementById(PREVIEW_ROOT_ID);
7169

72-
if (!previewWindow || !existingRoot) {
70+
if (!existingRoot) {
7371
return;
7472
}
7573

76-
existingRoot.classList.add('anima-motion-preview-root--hiding');
77-
78-
previewWindow.setTimeout(() => {
79-
const currentRoot = previewDocument.getElementById(PREVIEW_ROOT_ID);
80-
if (currentRoot) {
81-
currentRoot.remove();
82-
}
83-
}, PREVIEW_FADE_OUT_DELAY);
74+
existingRoot.classList.add('anima-motion-preview-root--settled');
8475
}
8576

8677
function renderMotionPreview(previewDocument, state, config = {}) {
@@ -103,9 +94,9 @@ function renderMotionPreview(previewDocument, state, config = {}) {
10394

10495
previewDocument.body.appendChild(previewRoot);
10596

106-
previewWindow.__animaMotionPreviewHideTimer = previewWindow.setTimeout(
107-
() => hideMotionPreview(previewDocument),
108-
config.previewDuration || PREVIEW_HIDE_DELAY
97+
previewWindow.__animaMotionPreviewSettleTimer = previewWindow.setTimeout(
98+
() => settleMotionPreview(previewDocument),
99+
config.previewSettleDelay || PREVIEW_SETTLE_DELAY
109100
);
110101
}
111102

src/scss/components/_page-transitions.scss

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,28 @@
188188
.c-loader--preview {
189189
display: block;
190190
opacity: 1;
191-
transition: opacity 0.18s ease-out;
192191
}
193192

194-
.anima-motion-preview-root--hiding {
195-
.c-page-transition-border--preview,
196-
.c-loader--preview {
197-
opacity: 0;
193+
.anima-motion-preview-root--settled {
194+
.border-logo-background {
195+
animation: none;
196+
transform: translate3d(-50%, -50%, 0) scaleY(1);
197+
}
198+
199+
.border-logo .logo {
200+
animation: none;
201+
opacity: 1;
202+
}
203+
204+
.border-logo-fill {
205+
animation: none;
206+
transform: translate3d(0, 0, 0);
207+
width: 50%;
208+
}
209+
210+
.border-logo-fill:after {
211+
animation: none;
212+
display: none;
198213
}
199214
}
200215

style-rtl.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

style.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
const test = require('node:test');
2+
const assert = require('node:assert/strict');
3+
4+
const {
5+
renderMotionPreview,
6+
} = require('../src/js/admin/customizer-motion-preview-dom.js');
7+
8+
function createFakeClassList(element) {
9+
return {
10+
add(className) {
11+
const classNames = new Set((element.className || '').split(/\s+/).filter(Boolean));
12+
classNames.add(className);
13+
element.className = Array.from(classNames).join(' ');
14+
},
15+
contains(className) {
16+
return (element.className || '').split(/\s+/).filter(Boolean).includes(className);
17+
},
18+
};
19+
}
20+
21+
function createFakeElement(tagName, document) {
22+
return {
23+
tagName,
24+
ownerDocument: document,
25+
className: '',
26+
innerHTML: '',
27+
parentNode: null,
28+
children: [],
29+
attributes: {},
30+
classList: null,
31+
setAttribute(name, value) {
32+
this.attributes[name] = value;
33+
if (name === 'id') {
34+
this.id = value;
35+
document.elements.set(value, this);
36+
}
37+
},
38+
appendChild(child) {
39+
child.parentNode = this;
40+
this.children.push(child);
41+
42+
if (child.id) {
43+
document.elements.set(child.id, child);
44+
}
45+
},
46+
remove() {
47+
if (this.id) {
48+
document.elements.delete(this.id);
49+
}
50+
51+
if (this.parentNode) {
52+
this.parentNode.children = this.parentNode.children.filter((child) => child !== this);
53+
}
54+
},
55+
};
56+
}
57+
58+
function createFakeDocument() {
59+
const timeouts = [];
60+
const clearedTimeouts = [];
61+
62+
const document = {
63+
elements: new Map(),
64+
body: null,
65+
createElement(tagName) {
66+
const element = createFakeElement(tagName, document);
67+
element.classList = createFakeClassList(element);
68+
69+
return element;
70+
},
71+
getElementById(id) {
72+
return document.elements.get(id) || null;
73+
},
74+
defaultView: {
75+
__animaMotionPreviewHideTimer: null,
76+
setTimeout(callback, delay) {
77+
const timer = { callback, delay };
78+
timeouts.push(timer);
79+
80+
return timer;
81+
},
82+
clearTimeout(timer) {
83+
clearedTimeouts.push(timer);
84+
},
85+
},
86+
__timeouts: timeouts,
87+
__clearedTimeouts: clearedTimeouts,
88+
};
89+
90+
document.body = document.createElement('body');
91+
92+
return document;
93+
}
94+
95+
test('motion preview settles into a held frame instead of removing itself after the first replay', () => {
96+
const previewDocument = createFakeDocument();
97+
98+
renderMotionPreview(
99+
previewDocument,
100+
{
101+
isVisible: true,
102+
pageTransitionStyle: 'border_iris',
103+
logoLoadingStyle: 'progress_bar',
104+
transitionSymbol: '',
105+
},
106+
{
107+
progressBarMarkup: '<div class="border-logo"><div class="logo">Logo</div></div>',
108+
previewSettleDelay: 1200,
109+
}
110+
);
111+
112+
const previewRoot = previewDocument.getElementById('anima-motion-preview-root');
113+
114+
assert.ok(previewRoot);
115+
assert.equal(previewDocument.__timeouts.length, 1);
116+
assert.equal(previewDocument.__timeouts[0].delay, 1200);
117+
118+
previewDocument.__timeouts[0].callback();
119+
120+
assert.equal(previewDocument.getElementById('anima-motion-preview-root'), previewRoot);
121+
assert.equal(previewRoot.classList.contains('anima-motion-preview-root--settled'), true);
122+
});

0 commit comments

Comments
 (0)