From 670215c7bf95b41ca637e4a6b114ea45de6ed8de Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 15 Jan 2025 15:29:13 -0800 Subject: [PATCH 1/5] Explore view transitions in Twenty Fifteen for post title and featured image specifically. --- .../twentyfifteen/css/view-transitions.css | 3 + .../themes/twentyfifteen/functions.php | 15 +++ .../twentyfifteen/js/view-transitions.js | 91 +++++++++++++++++++ 3 files changed, 109 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..8f778e466b6b1 --- /dev/null +++ b/src/wp-content/themes/twentyfifteen/css/view-transitions.css @@ -0,0 +1,3 @@ +@view-transition { + navigation: auto; +} diff --git a/src/wp-content/themes/twentyfifteen/functions.php b/src/wp-content/themes/twentyfifteen/functions.php index 903dddc1f1908..dffbe76d3aefe 100644 --- a/src/wp-content/themes/twentyfifteen/functions.php +++ b/src/wp-content/themes/twentyfifteen/functions.php @@ -474,6 +474,21 @@ function twentyfifteen_scripts() { 'collapse' => '' . __( 'collapse child menu', 'twentyfifteen' ) . '', ) ); + + wp_enqueue_style( + 'twentyfifteen-view-transitions', + get_template_directory_uri() . '/css/view-transitions.css', + array(), + '20250115' + ); + + // This script must be loaded prior to rendering, i.e. not in the footer and not deferred or async. + wp_enqueue_script( + 'twentyfifteen-view-transitions', + get_template_directory_uri() . '/js/view-transitions.js', + array(), + '20250115' + ); } 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..b9d3109d70d8f --- /dev/null +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -0,0 +1,91 @@ +if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { + const getParentElement = ( element, selector ) => { + element = element.parentElement; + while ( element && element !== document ) { + if ( ! selector || element.matches( selector ) ) { + return element; + } + } + return null; + }; + + const setTemporaryViewTransitionNames = async ( entries, vtPromise ) => { + for ( const [ element, name ] of entries ) { + if ( ! element ) { + continue; + } + element.style.viewTransitionName = name; + } + + await vtPromise; + + for ( const [ element, name ] of entries ) { + if ( ! element ) { + continue; + } + element.style.viewTransitionName = ''; + } + }; + + window.addEventListener( 'pageswap', ( e ) => { + if ( e.viewTransition ) { + if ( document.body.classList.contains( 'single' ) ) { + const article = document.querySelectorAll( 'article.post' ); + if ( article.length !== 1 ) { + return; + } + + setTemporaryViewTransitionNames( [ + [ article[ 0 ].querySelector( '.entry-title' ), 'post-title' ], + [ article[ 0 ].querySelector( '.post-thumbnail' ), 'post-thumbnail' ], + ], e.viewTransition.finished ); + } else if ( document.body.classList.contains( 'home' ) || document.body.classList.contains( 'archive' ) ) { + const articleLink = document.querySelector( 'article.post a[href="' + e.activation.entry.url + '"]' ); + if ( ! articleLink ) { + return; + } + + const article = getParentElement( articleLink, 'article.post' ); + + setTemporaryViewTransitionNames( [ + [ article.querySelector( '.entry-title' ), 'post-title' ], + [ article.querySelector( '.post-thumbnail' ), 'post-thumbnail' ], + ], e.viewTransition.finished ); + } + } + } ); + + window.addEventListener( 'pagereveal', ( e ) => { + if ( ! window.navigation.activation.from ) { + return; + } + + if ( e.viewTransition ) { + if ( document.body.classList.contains( 'single' ) ) { + const article = document.querySelectorAll( 'article.post' ); + if ( article.length !== 1 ) { + return; + } + + setTemporaryViewTransitionNames( [ + [ article[ 0 ].querySelector( '.entry-title' ), 'post-title' ], + [ article[ 0 ].querySelector( '.post-thumbnail' ), 'post-thumbnail' ], + ], e.viewTransition.ready ); + } else if ( document.body.classList.contains( 'home' ) || document.body.classList.contains( 'archive' ) ) { + const articleLink = document.querySelector( 'article.post a[href="' + window.navigation.activation.from.url + '"]' ); + if ( ! articleLink ) { + return; + } + + const article = getParentElement( articleLink, 'article.post' ); + + setTemporaryViewTransitionNames( [ + [ article.querySelector( '.entry-title' ), 'post-title' ], + [ article.querySelector( '.post-thumbnail' ), 'post-thumbnail' ], + ], e.viewTransition.ready ); + } + } + } ); +} else { + window.console.warn( 'View transitions not loaded as the browser is lacking support.' ); +} From 761369cc8940e8f9d277d86c2e0803688d825827 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 15 Jan 2025 15:39:13 -0800 Subject: [PATCH 2/5] Fix unused variable. --- src/wp-content/themes/twentyfifteen/js/view-transitions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-content/themes/twentyfifteen/js/view-transitions.js b/src/wp-content/themes/twentyfifteen/js/view-transitions.js index b9d3109d70d8f..c8bf45a44ca20 100644 --- a/src/wp-content/themes/twentyfifteen/js/view-transitions.js +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -19,7 +19,7 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { await vtPromise; - for ( const [ element, name ] of entries ) { + for ( const [ element, _ ] of entries ) { if ( ! element ) { continue; } From 30b15f8d21a81b83767c7f58e5bb3ff2674311a8 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 11 Feb 2025 10:44:33 -0800 Subject: [PATCH 3/5] Return early if no parent article found. --- src/wp-content/themes/twentyfifteen/js/view-transitions.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wp-content/themes/twentyfifteen/js/view-transitions.js b/src/wp-content/themes/twentyfifteen/js/view-transitions.js index c8bf45a44ca20..255541b433b5c 100644 --- a/src/wp-content/themes/twentyfifteen/js/view-transitions.js +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -46,6 +46,9 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { } const article = getParentElement( articleLink, 'article.post' ); + if ( ! article ) { + return; + } setTemporaryViewTransitionNames( [ [ article.querySelector( '.entry-title' ), 'post-title' ], From 22eeb8328bdd737eb1fd8d280a59ec11b70c8499 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Tue, 11 Feb 2025 10:45:10 -0800 Subject: [PATCH 4/5] Return early if no parent article found. --- src/wp-content/themes/twentyfifteen/js/view-transitions.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wp-content/themes/twentyfifteen/js/view-transitions.js b/src/wp-content/themes/twentyfifteen/js/view-transitions.js index 255541b433b5c..02abf35ce246a 100644 --- a/src/wp-content/themes/twentyfifteen/js/view-transitions.js +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -81,6 +81,9 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { } const article = getParentElement( articleLink, 'article.post' ); + if ( ! article ) { + return; + } setTemporaryViewTransitionNames( [ [ article.querySelector( '.entry-title' ), 'post-title' ], From ab9b25b3d7e53b622f4b8847ad1774f551099fbd Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Wed, 12 Feb 2025 15:51:35 -0800 Subject: [PATCH 5/5] Use Element.closest instead of broken custom function. --- .../themes/twentyfifteen/js/view-transitions.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/wp-content/themes/twentyfifteen/js/view-transitions.js b/src/wp-content/themes/twentyfifteen/js/view-transitions.js index 02abf35ce246a..20232853b5f1d 100644 --- a/src/wp-content/themes/twentyfifteen/js/view-transitions.js +++ b/src/wp-content/themes/twentyfifteen/js/view-transitions.js @@ -1,14 +1,4 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { - const getParentElement = ( element, selector ) => { - element = element.parentElement; - while ( element && element !== document ) { - if ( ! selector || element.matches( selector ) ) { - return element; - } - } - return null; - }; - const setTemporaryViewTransitionNames = async ( entries, vtPromise ) => { for ( const [ element, name ] of entries ) { if ( ! element ) { @@ -45,7 +35,7 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { return; } - const article = getParentElement( articleLink, 'article.post' ); + const article = articleLink.closest( 'article.post' ); if ( ! article ) { return; } @@ -80,7 +70,7 @@ if ( !! window.navigation && 'CSSViewTransitionRule' in window ) { return; } - const article = getParentElement( articleLink, 'article.post' ); + const article = articleLink.closest( 'article.post' ); if ( ! article ) { return; }