Skip to content

Commit f525d56

Browse files
committed
feat: Implement Spatial Theme Transition (The Wave) (#8856)
1 parent b046edf commit f525d56

3 files changed

Lines changed: 58 additions & 2 deletions

File tree

apps/portal/view/ViewportController.mjs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,34 @@ class ViewportController extends Controller {
273273
/**
274274
* @param {Object} data
275275
*/
276-
onSwitchTheme(data) {
276+
async onSwitchTheme(data) {
277277
let me = this,
278278
viewport = me.component,
279279
oldTheme = viewport.theme || 'neo-theme-neo-light',
280-
newTheme = oldTheme === 'neo-theme-neo-light' ? 'neo-theme-neo-dark' : 'neo-theme-neo-light';
280+
newTheme = oldTheme === 'neo-theme-neo-light' ? 'neo-theme-neo-dark' : 'neo-theme-neo-light',
281+
radius, x, y;
282+
283+
if (data.clientX) {
284+
x = data.clientX;
285+
y = data.clientY;
286+
radius = Math.hypot(Math.max(x, 3000 - x), Math.max(y, 3000 - y)) // simplified max calculation
287+
}
288+
289+
await Neo.main.DomAccess.startViewTransition({
290+
animate: {
291+
keyframes: [
292+
{clipPath: `circle(0px at ${x}px ${y}px)`},
293+
{clipPath: `circle(${radius}px at ${x}px ${y}px)`}
294+
],
295+
options: {
296+
duration : 500,
297+
easing : 'ease-in',
298+
pseudoElement: '::view-transition-new(root)'
299+
}
300+
},
301+
delay : 100,
302+
windowId: me.windowId
303+
});
281304

282305
me.setTheme(newTheme)
283306
}

resources/scss/src/apps/portal/Viewport.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ body {
77
}
88
}
99

10+
::view-transition-old(root),
11+
::view-transition-new(root) {
12+
animation : none;
13+
mix-blend-mode: normal;
14+
}
1015

1116
.neo-viewport {
1217
// sometimes when transitioning between card & cube layouts, the flex value does get lost

src/main/DomAccess.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class DomAccess extends Base {
8282
'selectNode',
8383
'setBodyCls',
8484
'setStyle',
85+
'startViewTransition',
8586
'syncModalMask',
8687
'trapFocus',
8788
'windowScrollTo'
@@ -862,6 +863,33 @@ class DomAccess extends Base {
862863
})
863864
}
864865

866+
/**
867+
* @param {Object} data
868+
* @param {Object} [data.animate]
869+
* @param {Number} [data.delay=50]
870+
* @returns {Promise<Boolean>}
871+
*/
872+
async startViewTransition(data) {
873+
if (!document.startViewTransition) {
874+
return false
875+
}
876+
877+
const transition = document.startViewTransition(async () => {
878+
await this.timeout(data.delay || 50)
879+
});
880+
881+
if (data.animate) {
882+
transition.ready.then(() => {
883+
document.documentElement.animate(
884+
data.animate.keyframes,
885+
data.animate.options
886+
)
887+
})
888+
}
889+
890+
return true
891+
}
892+
865893
/**
866894
* See: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollBy
867895
* @param {Object} data

0 commit comments

Comments
 (0)