Skip to content
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

Interactivity Router: Move ARIA live region and loading bar to the Interactivity Router #58377

Merged
merged 25 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
66d0dbb
Expose state related to navigations
DAreRodz Jan 29, 2024
07bbaad
Remove loading bar and aria region from query block
DAreRodz Jan 29, 2024
e56191d
Implement wp-router-region processor
DAreRodz Jan 29, 2024
c2ab4d2
Remove aria regions and loading bar logic from query block
DAreRodz Jan 29, 2024
e0fecdc
Move loading bar CSS from query to router region processor
DAreRodz Jan 29, 2024
020e9c2
Recover `navigatingTo` variable
DAreRodz Jan 29, 2024
f45282b
Fix flaky test
DAreRodz Jan 29, 2024
2f95ca7
Remove unnecessary PHPUnit checks
DAreRodz Jan 29, 2024
eb65d2b
Ensure the callback is executed once
DAreRodz Feb 1, 2024
6ab84a1
Update boolean flags and message only if page exists
DAreRodz Feb 1, 2024
1c4445f
Clarify usage of unresolved promise
DAreRodz Feb 1, 2024
f207a79
More code reordering
DAreRodz Feb 1, 2024
56225f5
Save current link URL after navigating
DAreRodz Feb 1, 2024
04ce0dd
Add topLoadingBar and screenReaderAnnounce options
DAreRodz Feb 2, 2024
8217089
Fix url updating after navigating back or forward
DAreRodz Feb 2, 2024
196634c
Rename internal `url` variable to `pagePath`
DAreRodz Feb 2, 2024
4e7660f
Always set a string in `state.url`
DAreRodz Feb 2, 2024
ab00ba8
Remove confusing comment
DAreRodz Feb 2, 2024
1960203
Use internal state instance instead of `wp_interactivity_state`
DAreRodz Feb 2, 2024
a13b08c
Add id to the router animations style tag
DAreRodz Feb 2, 2024
9917541
Test the `data-wp-router-region` directive processor
DAreRodz Feb 2, 2024
e63e717
Rename topLoadingBar option to loadingAnimation
DAreRodz Feb 2, 2024
7d64b03
Update docs for options.loadingAnimation
DAreRodz Feb 2, 2024
bd3842c
Move router-region flag to the WP_Interactivity_API class
DAreRodz Feb 2, 2024
e08f981
Fix screenReaderAnnouncement name
DAreRodz Feb 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ class WP_Interactivity_API {
* @var array
*/
private static $directive_processors = array(
'data-wp-interactive' => 'data_wp_interactive_processor',
'data-wp-context' => 'data_wp_context_processor',
'data-wp-bind' => 'data_wp_bind_processor',
'data-wp-class' => 'data_wp_class_processor',
'data-wp-style' => 'data_wp_style_processor',
'data-wp-text' => 'data_wp_text_processor',
'data-wp-interactive' => 'data_wp_interactive_processor',
'data-wp-router-region' => 'data_wp_router_region_processor',
'data-wp-context' => 'data_wp_context_processor',
'data-wp-bind' => 'data_wp_bind_processor',
'data-wp-class' => 'data_wp_class_processor',
'data-wp-style' => 'data_wp_style_processor',
'data-wp-text' => 'data_wp_text_processor',
);

/**
Expand All @@ -49,6 +50,21 @@ class WP_Interactivity_API {
*/
private $config_data = array();

/**
* Flag that indicates whether the `data-wp-router-region` directive has
* been found in the HTML and processed.
*
* The value is saved in a private property of the WP_Interactivity_API
* instance instead of using a static variable inside the processor
* function, which would hold the same value for all instances
* independently of whether they have processed any
* `data-wp-router-region` directive or not.
*
* @since 6.5.0
* @var bool
*/
private $has_processed_router_region = false;

/**
* Gets and/or sets the initial state of an Interactivity API store for a
* given namespace.
Expand Down Expand Up @@ -673,6 +689,88 @@ private function data_wp_text_processor( WP_Interactivity_API_Directives_Process
}
}
}

/**
* Processes the `data-wp-router-region` directive.
*
* It renders in the footer a set of HTML elements to notify users about
* client-side navigations. More concretely, the elements added are 1) a
* top loading bar to visually inform that a navigation is in progress
* and 2) an `aria-live` region for accessible navigation announcements.
*
* @since 6.5.0
*
* @param WP_Interactivity_API_Directives_Processor $p The directives processor instance.
*/
private function data_wp_router_region_processor( WP_Interactivity_API_Directives_Processor $p ) {
if ( ! $p->is_tag_closer() && ! $this->has_processed_router_region ) {
$this->has_processed_router_region = true;

// Initialize the `core/router` store.
$this->state(
'core/router',
array(
'navigation' => array(
'message' => '',
'hasStarted' => false,
'hasFinished' => false,
'texts' => array(
'loading' => __( 'Loading page, please wait.' ),
'loaded' => __( 'Page Loaded.' ),
),
),
)
);

$callback = static function () {
echo <<<HTML
<style id="wp-interactivity-router_animations">
.wp-interactivity-router_loading-bar {
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 100vw;
max-width: 100vw !important;
height: 4px;
background-color: var(--wp--preset--color--primary, #000);
opacity: 0
}
.wp-interactivity-router_loading-bar.start-animation {
animation: wp-interactivity-router_loading-bar-start-animation 30s cubic-bezier(0.03, 0.5, 0, 1) forwards
}
.wp-interactivity-router_loading-bar.finish-animation {
animation: wp-interactivity-router_loading-bar-finish-animation 300ms ease-in
}
@keyframes wp-interactivity-router_loading-bar-start-animation {
0% { transform: scaleX(0); transform-origin: 0% 0%; opacity: 1 }
100% { transform: scaleX(1); transform-origin: 0% 0%; opacity: 1 }
}
@keyframes wp-interactivity-router_loading-bar-finish-animation {
0% { opacity: 1 }
50% { opacity: 1 }
100% { opacity: 0 }
}
</style>
<div
class="wp-interactivity-router_loading-bar"
data-wp-interactive='{"namespace":"core/router"}'
data-wp-class--start-animation="state.navigation.hasStarted"
data-wp-class--finish-animation="state.navigation.hasFinished"
></div>
<div
class="screen-reader-text"
aria-live="polite"
data-wp-interactive='{"namespace":"core/router"}'
data-wp-text="state.navigation.message"
></div>
HTML;
};
add_action( 'wp_footer', $callback );
luisherranz marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

}
3 changes: 1 addition & 2 deletions packages/block-library/src/query/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,5 @@
"html": false,
"layout": true
},
"editorStyle": "wp-block-query-editor",
"style": "wp-block-query"
"editorStyle": "wp-block-query-editor"
}
37 changes: 1 addition & 36 deletions packages/block-library/src/query/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,43 +30,8 @@ function render_block_core_query( $attributes, $content, $block ) {
$p->set_attribute( 'data-wp-interactive', '{"namespace":"core/query"}' );
$p->set_attribute( 'data-wp-router-region', 'query-' . $attributes['queryId'] );
$p->set_attribute( 'data-wp-init', 'callbacks.setQueryRef' );
// Use context to send translated strings.
$p->set_attribute(
'data-wp-context',
wp_json_encode(
array(
'loadingText' => __( 'Loading page, please wait.' ),
'loadedText' => __( 'Page Loaded.' ),
),
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP
)
);
$p->set_attribute( 'data-wp-context', '{}' );
$content = $p->get_updated_html();

// Mark the block as interactive.
$block->block_type->supports['interactivity'] = true;

// Add a div to announce messages using `aria-live`.
$html_tag = 'div';
if ( ! empty( $attributes['tagName'] ) ) {
$html_tag = esc_attr( $attributes['tagName'] );
}
$last_tag_position = strripos( $content, '</' . $html_tag . '>' );
$content = substr_replace(
$content,
'<div
class="screen-reader-text"
aria-live="polite"
data-wp-text="context.message"
></div>
<div
class="wp-block-query__enhanced-pagination-animation"
data-wp-class--start-animation="state.startAnimation"
data-wp-class--finish-animation="state.finishAnimation"
></div>',
$last_tag_position,
0
);
}
}

Expand Down
52 changes: 0 additions & 52 deletions packages/block-library/src/query/style.scss

This file was deleted.

26 changes: 0 additions & 26 deletions packages/block-library/src/query/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@ const isValidEvent = ( event ) =>
! event.defaultPrevented;

store( 'core/query', {
state: {
get startAnimation() {
return getContext().animation === 'start';
},
get finishAnimation() {
return getContext().animation === 'finish';
},
},
actions: {
*navigate( event ) {
const ctx = getContext();
Expand All @@ -37,28 +29,10 @@ store( 'core/query', {
if ( isValidLink( ref ) && isValidEvent( event ) && ! isDisabled ) {
event.preventDefault();

// Don't announce the navigation immediately, wait 400 ms.
const timeout = setTimeout( () => {
ctx.message = ctx.loadingText;
ctx.animation = 'start';
}, 400 );

const { actions } = yield import(
'@wordpress/interactivity-router'
);
yield actions.navigate( ref.href );

// Dismiss loading message if it hasn't been added yet.
clearTimeout( timeout );

// Announce that the page has been loaded. If the message is the
// same, we use a no-break space similar to the @wordpress/a11y
// package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26
ctx.message =
ctx.loadedText +
( ctx.message === ctx.loadedText ? '\u00A0' : '' );

ctx.animation = 'finish';
ctx.url = ref.href;
luisherranz marked this conversation as resolved.
Show resolved Hide resolved

// Focus the first anchor of the Query block.
Expand Down
Loading
Loading