From b43b36195a20465199e207d7b6fe0f92f9b30b37 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 19 Dec 2024 03:27:27 -0800 Subject: [PATCH] Experiment with cross-document view transitions in Twenty Fifteen theme. --- .../twentyfifteen/css/view-transitions.css | 58 ++++++++++++++++++ .../themes/twentyfifteen/functions.php | 18 ++++++ .../twentyfifteen/js/view-transitions.js | 61 +++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/wp-content/themes/twentyfifteen/css/view-transitions.css create mode 100644 src/wp-content/themes/twentyfifteen/js/view-transitions.js diff --git a/src/wp-content/themes/twentyfifteen/css/view-transitions.css b/src/wp-content/themes/twentyfifteen/css/view-transitions.css new file mode 100644 index 0000000000000..f0f085dc42553 --- /dev/null +++ b/src/wp-content/themes/twentyfifteen/css/view-transitions.css @@ -0,0 +1,58 @@ +@view-transition { + navigation: auto; +} + +::view-transition-group(*) { + animation-duration: 1s; +} + +@keyframes slide-in-from-left { + from { + translate: -100vw 0; + } +} + +@keyframes slide-in-from-right { + from { + translate: 100vw 0; + } +} + +@keyframes slide-out-to-left { + to { + translate: -100vw 0; + } +} + +@keyframes slide-out-to-right { + to { + translate: 100vw 0; + } +} + +html:active-view-transition-type(forwards, backwards) { + :root { + view-transition-name: none; + } + main { + view-transition-name: main; + } +} + +html:active-view-transition-type(forwards) { + &::view-transition-old(main) { + animation-name: slide-out-to-left; + } + &::view-transition-new(main) { + animation-name: slide-in-from-right; + } +} + +html:active-view-transition-type(backwards) { + &::view-transition-old(main) { + animation-name: slide-out-to-right; + } + &::view-transition-new(main) { + animation-name: slide-in-from-left; + } +} diff --git a/src/wp-content/themes/twentyfifteen/functions.php b/src/wp-content/themes/twentyfifteen/functions.php index 903dddc1f1908..1afbf4c5976e7 100644 --- a/src/wp-content/themes/twentyfifteen/functions.php +++ b/src/wp-content/themes/twentyfifteen/functions.php @@ -474,6 +474,24 @@ function twentyfifteen_scripts() { 'collapse' => '' . __( 'collapse child menu', 'twentyfifteen' ) . '', ) ); + + wp_enqueue_style( + 'twentyfifteen-view-transitions', + get_template_directory_uri() . '/css/view-transitions.css', + array(), + '20241219' + ); + + wp_enqueue_script( + 'twentyfifteen-view-transitions', + get_template_directory_uri() . '/js/view-transitions.js', + array(), + '20241219', + array( + 'in_footer' => false, + 'strategy' => 'defer', + ) + ); } add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' ); diff --git a/src/wp-content/themes/twentyfifteen/js/view-transitions.js b/src/wp-content/themes/twentyfifteen/js/view-transitions.js new file mode 100644 index 0000000000000..bf8d88422b8e7 --- /dev/null +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -0,0 +1,61 @@ +// TODO: Check for `!! window.navigation && 'CSSViewTransitionRule' in window`. + +const determineTransitionType = ( oldNavigationEntry, newNavigationEntry ) => { + if ( ! oldNavigationEntry || ! newNavigationEntry ) { + return 'unknown'; + } + + const currentURL = new URL( oldNavigationEntry.url ); + const destinationURL = new URL( newNavigationEntry.url ); + + const currentPathname = currentURL.pathname; + const destinationPathname = destinationURL.pathname; + + if ( currentPathname !== destinationPathname ) { + // If post URLs start with a date, use that to determine "order". + const currentDateMatches = currentPathname.match( /^\/(\d{4})\/(\d{2})\/(\d{2})\// ); + const destinationDateMatches = destinationPathname.match( /^\/(\d{4})\/(\d{2})\/(\d{2})\// ); + console.log( currentPathname ); + console.log( destinationPathname ); + if ( currentDateMatches && destinationDateMatches ) { + const currentDate = new Date( parseInt( currentDateMatches[ 1 ] ), parseInt( currentDateMatches[ 2 ] ) - 1, parseInt( currentDateMatches[ 3 ] ) ); + const destinationDate = new Date( parseInt( destinationDateMatches[ 1 ] ), parseInt( destinationDateMatches[ 2 ] ) - 1, parseInt( destinationDateMatches[ 3 ] ) ); + if ( currentDate < destinationDate ) { + return 'forwards'; + } + if ( currentDate > destinationDate ) { + return 'backwards'; + } + return 'unknown'; + } + + // Otherwise, check URL "hierarchy". + if ( destinationPathname.startsWith( currentPathname ) ) { + return 'forwards'; + } + if ( currentPathname.startsWith( destinationPathname ) ) { + return 'backwards'; + } + } + + return 'unknown'; +}; + +window.addEventListener( 'pageswap', async ( e ) => { + if ( e.viewTransition ) { + const transitionType = determineTransitionType( e.activation.from, e.activation.entry ); + + console.log( `pageSwap: ${ transitionType }` ); + e.viewTransition.types.add( transitionType ); + } +} ); + +window.addEventListener( 'pagereveal', async ( e ) => { + console.log( 'pageRevealEvent', e ); + if ( e.viewTransition ) { + const transitionType = determineTransitionType( navigation.activation.from, navigation.activation.entry ); + + console.log( `pageReveal: ${ transitionType }` ); + e.viewTransition.types.add( transitionType ); + } +} );