Skip to content

Add support for dynamic view transition names for global elements, and certain post elements to View Transitions plugin #1999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: trunk
Choose a base branch
from

Conversation

felixarntz
Copy link
Member

Summary

See #1997.

Relevant technical choices

  • Follow up to Scaffold View Transitions feature plugin #1998.
  • Adds support for certain view transition names, some for global elements (e.g. header, main), others for post specific elements like post titles and post featured images.
  • The specific element selectors and their view transition names can be optionally specified via view-transitions theme support. The defaults cover both block themes (standardized via Core blocks) and classic themes (via common conventions and partially Core CSS classes), and should work for the majority of themes.

@felixarntz felixarntz added [Type] Enhancement A suggestion for improvement of an existing feature no milestone PRs that do not have a defined milestone for release [Plugin] View Transitions Issues for the View Transitions plugin labels Apr 30, 2025
* identified by config.postSelector) and their view transition names.
*/
window.plvtInitViewTransitions = ( config ) => {
if ( ! window.navigation || ! ( 'CSSViewTransitionRule' in window ) ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swissspidy I get TypeScript warnings locally here, like navigation not being a valid property on window, etc. The same in regards to the various (valid) properties accessed on the event objects. Do you have any advice for how to fix them?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Navigation API is still relatively new and only supported by Chromium-based browsers. TypeScript by default only ships such types if the feature is supported by at least 2 different browser engines.

Until that happens, you can use the community-maintained navigation-api-types package.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that, but it looks like that package doesn't properly support the latest specification either. It doesn't support e.g. the activation property of https://developer.mozilla.org/en-US/docs/Web/API/Navigation, which is what's needed here. So using this package doesn't resolve the issue, for now I ended up manually typing it on a custom ExtendedWindow type.

Copy link

github-actions bot commented Apr 30, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: felixarntz <[email protected]>
Co-authored-by: swissspidy <[email protected]>
Co-authored-by: ShyamGadde <[email protected]>
Co-authored-by: westonruter <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

/**
* Customizes view transition behavior on the URL that is being navigated from.
*
* @param {Event} event Event fired as the previous URL is about to unload.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param {Event} event Event fired as the previous URL is about to unload.
* @param {PageSwapEvent} event Event fired as the previous URL is about to unload.

That should help with those errors below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it like that originally actually, but that would give me other errors about PageSwapEvent / PageRevealEvent being undefined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made several updates in 8545b4f, which resolves all errors except those related to PageSwapEvent and PageRevealEvent.

I am confused why these warnings still appear because:

  • Both PageSwapEvent and PageRevealEvent are declared in TypeScript's own dom library. I verified that they're there in the version we currently use.
  • The errors all refer to Event (instead of the above two), which I'm puzzled why they do that, even though the JS and TS code refers to PageSwapEvent and PageRevealEvent.

Let me know if you have any ideas.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm looking at 8545b4f, instead of adding such a ExtendedWindow type, you should extend the Window interface. Like so:

declare global {
	interface Window {
		plvtInitViewTransitions?: InitViewTransitionsFunction;
		navigation?: {
			activation: NavigationActivation;
		};
	}
}

There's no need for this const win = window; part (and it doesn't affect minification anyway, so the comment there is incorrect).

The PageSwapEvent errors I can look at tomorrow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks, fixed in eaf9060. I took the comment from Optimization Detective's detect.js, which assigns const win = window with that comment, so I thought that had a purpose.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I would follow #1999 (comment) for now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks, fixed in eaf9060. I took the comment from Optimization Detective's detect.js, which assigns const win = window with that comment, so I thought that had a purpose.

For this line:

The purpose was indeed to facilitate minification, since the window global symbol won't be used in favor of win which can be further reduced during minification to something like w.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK minifiers automatically do that kind of stuff. I'd be very surprised if one needs to help them like that 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried eliminating win in favor of reusing window and the minification used in this repo doesn't introduce any minified alias:

if (0 === window.innerWidth || 0 === window.innerHeight) return void y("Window must have non-zero dimensions for URL Metric collection.");

Otherwise, when minified it is passing through the symbol as-is:

if (0 === win.innerWidth || 0 === win.innerHeight) return void y("Window must have non-zero dimensions for URL Metric collection.");

I'm also surprised that the existing minifier isn't doing something smarter by reducing win to w since it is a local variable in the module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the ESLint problem, I applied the suggested code from @ShyamGadde, that's indeed better. Everything passes now 👍

Copy link

codecov bot commented May 1, 2025

Codecov Report

Attention: Patch coverage is 67.18750% with 21 lines in your changes missing coverage. Please review.

Project coverage is 72.47%. Comparing base (565ed5e) to head (b970e29).

Files with missing lines Patch % Lines
plugins/view-transitions/includes/functions.php 41.17% 10 Missing ⚠️
plugins/view-transitions/includes/theme.php 78.26% 10 Missing ⚠️
plugins/view-transitions/hooks.php 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #1999      +/-   ##
==========================================
- Coverage   72.72%   72.47%   -0.25%     
==========================================
  Files          87       88       +1     
  Lines        7127     7100      -27     
==========================================
- Hits         5183     5146      -37     
- Misses       1944     1954      +10     
Flag Coverage Δ
multisite 72.47% <67.18%> (-0.25%) ⬇️
single 40.64% <67.18%> (-0.37%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

*
* @global array<string, mixed> $_wp_theme_features Theme support features added and their arguments.
*/
function plvt_sanitize_view_transitions_theme_support(): void {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: Instead of having plvt_sanitize_view_transitions_theme_support() sanitize the global variable and then override $_wp_theme_features with the sanitized value, what if there was instead a plvt_get_view_transitions_theme_support() which always returned the sanitized value? Then there would be no need to set plvt_sanitize_view_transitions_theme_support() at init action, and there wouldn't be a risk that a theme made changes to the theme support after the init action happened.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, though I personally think the risk is low enough to ignore it in favor of having a more Core-like API, relying on the actual functions that should be used for this and "patching" the lack of integrated sanitization via a hook like this.

If later there are reports of problems with this, we could reassess the relevance.

@@ -42,4 +103,44 @@ function plvt_load_view_transitions(): void {
wp_register_style( 'wp-view-transitions', false, array(), null ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
wp_add_inline_style( 'wp-view-transitions', $stylesheet );
wp_enqueue_style( 'wp-view-transitions' );

$theme_support = get_theme_support( 'view-transitions' );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per above, this could be replaced with:

Suggested change
$theme_support = get_theme_support( 'view-transitions' );
$theme_support = plvt_get_view_transitions_theme_support();

Comment on lines +113 to +114
( ! is_array( $theme_support['global-transition-names'] ) || count( $theme_support['global-transition-names'] ) === 0 ) &&
( ! is_array( $theme_support['post-transition-names'] ) || count( $theme_support['post-transition-names'] ) === 0 )
Copy link
Member

@westonruter westonruter May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the is_array() checks if the theme support value has been sanitized, right?

Suggested change
( ! is_array( $theme_support['global-transition-names'] ) || count( $theme_support['global-transition-names'] ) === 0 ) &&
( ! is_array( $theme_support['post-transition-names'] ) || count( $theme_support['post-transition-names'] ) === 0 )
count( $theme_support['global-transition-names'] ) === 0 &&
count( $theme_support['post-transition-names'] ) === 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, but since the data comes from a global variable, I think it's better to use defensive coding.

@felixarntz felixarntz requested a review from westonruter May 6, 2025 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no milestone PRs that do not have a defined milestone for release [Plugin] View Transitions Issues for the View Transitions plugin [Type] Enhancement A suggestion for improvement of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants