Toolbar: Accessibility: Keyboard navigation for screen readers.
Change the admin toolbar to have `role="menu"` and support opening for screen readers. Remove screen reader only log out link and collapse duplicate profile links into one link. This is an imperfect solution to a complex problem in the adminbar, but the lack of screen reader access to submenus is a major accessibility problem, and this fix provides access, even if the mechanism is imperfect. Screen reader log out added in [21452]. Props abletec, Cheffheid, sabernhardt, alexstine, joedolson, afercia, sparklingrobots, danieltj, swissspidy, netweb, dionysous. Fixes #34668, #43633. Built from https://develop.svn.wordpress.org/trunk@57708 git-svn-id: http://core.svn.wordpress.org/trunk@57209 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
25ae4b9733
commit
059878b96d
|
@ -139,6 +139,9 @@ function wp_admin_bar_wp_menu( $wp_admin_bar ) {
|
|||
__( 'About WordPress' ) .
|
||||
'</span>',
|
||||
'href' => $about_url,
|
||||
'meta' => array(
|
||||
'menu_title' => __( 'About WordPress' ),
|
||||
),
|
||||
);
|
||||
|
||||
// Set tabindex="0" to make sub menus accessible when no URL is available.
|
||||
|
@ -283,6 +286,7 @@ function wp_admin_bar_my_account_item( $wp_admin_bar ) {
|
|||
'href' => $profile_url,
|
||||
'meta' => array(
|
||||
'class' => $class,
|
||||
'menu_title' => sprintf( __( 'Howdy, %s' ), $current_user->display_name ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -325,29 +329,17 @@ function wp_admin_bar_my_account_menu( $wp_admin_bar ) {
|
|||
$user_info .= "<span class='username'>{$current_user->user_login}</span>";
|
||||
}
|
||||
|
||||
$user_info .= "<span class='edit-profile'>" . __( 'Edit Profile' ) . '</span>';
|
||||
|
||||
$wp_admin_bar->add_node(
|
||||
array(
|
||||
'parent' => 'user-actions',
|
||||
'id' => 'user-info',
|
||||
'title' => $user_info,
|
||||
'href' => $profile_url,
|
||||
'meta' => array(
|
||||
'tabindex' => -1,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if ( false !== $profile_url ) {
|
||||
$wp_admin_bar->add_node(
|
||||
array(
|
||||
'parent' => 'user-actions',
|
||||
'id' => 'edit-profile',
|
||||
'title' => __( 'Edit Profile' ),
|
||||
'href' => $profile_url,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$wp_admin_bar->add_node(
|
||||
array(
|
||||
'parent' => 'user-actions',
|
||||
|
@ -397,6 +389,9 @@ function wp_admin_bar_site_menu( $wp_admin_bar ) {
|
|||
'id' => 'site-name',
|
||||
'title' => $title,
|
||||
'href' => ( is_admin() || ! current_user_can( 'read' ) ) ? home_url( '/' ) : admin_url(),
|
||||
'meta' => array(
|
||||
'menu_title' => $title,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -994,6 +989,9 @@ function wp_admin_bar_new_content_menu( $wp_admin_bar ) {
|
|||
'id' => 'new-content',
|
||||
'title' => $title,
|
||||
'href' => admin_url( current( array_keys( $actions ) ) ),
|
||||
'meta' => array(
|
||||
'menu_title' => _x( 'New', 'admin bar menu group label' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ class WP_Admin_Bar {
|
|||
*
|
||||
* @since 3.1.0
|
||||
* @since 4.5.0 Added the ability to pass 'lang' and 'dir' meta data.
|
||||
* @since 6.5.0 Added the ability to pass 'menu_title' for an ARIA menu name.
|
||||
*
|
||||
* @param array $args {
|
||||
* Arguments for adding a node.
|
||||
|
@ -117,7 +118,7 @@ class WP_Admin_Bar {
|
|||
* @type string $href Optional. Link for the item.
|
||||
* @type bool $group Optional. Whether or not the node is a group. Default false.
|
||||
* @type array $meta Meta data including the following keys: 'html', 'class', 'rel', 'lang', 'dir',
|
||||
* 'onclick', 'target', 'title', 'tabindex'. Default empty.
|
||||
* 'onclick', 'target', 'title', 'tabindex', 'menu_title'. Default empty.
|
||||
* }
|
||||
*/
|
||||
public function add_node( $args ) {
|
||||
|
@ -478,9 +479,6 @@ class WP_Admin_Bar {
|
|||
}
|
||||
?>
|
||||
</div>
|
||||
<?php if ( is_user_logged_in() ) : ?>
|
||||
<a class="screen-reader-shortcut" href="<?php echo esc_url( wp_logout_url() ); ?>"><?php _e( 'Log Out' ); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
@ -505,10 +503,12 @@ class WP_Admin_Bar {
|
|||
|
||||
/**
|
||||
* @since 3.3.0
|
||||
* @since 6.5.0 Added `$menu_title` parameter to allow an ARIA menu name.
|
||||
*
|
||||
* @param object $node
|
||||
* @param string|bool $menu_title The accessible name of this aria menu or false if not provided.
|
||||
*/
|
||||
final protected function _render_group( $node ) {
|
||||
final protected function _render_group( $node, $menu_title = false ) {
|
||||
if ( 'container' === $node->type ) {
|
||||
$this->_render_container( $node );
|
||||
return;
|
||||
|
@ -523,7 +523,11 @@ class WP_Admin_Bar {
|
|||
$class = '';
|
||||
}
|
||||
|
||||
echo "<ul id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$class>";
|
||||
if ( empty( $menu_title ) ) {
|
||||
echo "<ul role='menu' id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$class>";
|
||||
} else {
|
||||
echo "<ul role='menu' aria-label='" . esc_attr( $menu_title ) . "' id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$class>";
|
||||
}
|
||||
foreach ( $node->children as $item ) {
|
||||
$this->_render_item( $item );
|
||||
}
|
||||
|
@ -548,13 +552,14 @@ class WP_Admin_Bar {
|
|||
// Allow only numeric values, then casted to integers, and allow a tabindex value of `0` for a11y.
|
||||
$tabindex = ( isset( $node->meta['tabindex'] ) && is_numeric( $node->meta['tabindex'] ) ) ? (int) $node->meta['tabindex'] : '';
|
||||
$aria_attributes = ( '' !== $tabindex ) ? ' tabindex="' . $tabindex . '"' : '';
|
||||
$aria_attributes .= ' role="menuitem"';
|
||||
|
||||
$menuclass = '';
|
||||
$arrow = '';
|
||||
|
||||
if ( $is_parent ) {
|
||||
$menuclass = 'menupop ';
|
||||
$aria_attributes .= ' aria-haspopup="true"';
|
||||
$aria_attributes .= ' aria-expanded="false"';
|
||||
}
|
||||
|
||||
if ( ! empty( $node->meta['class'] ) ) {
|
||||
|
@ -603,7 +608,11 @@ class WP_Admin_Bar {
|
|||
if ( $is_parent ) {
|
||||
echo '<div class="ab-sub-wrapper">';
|
||||
foreach ( $node->children as $group ) {
|
||||
$this->_render_group( $group );
|
||||
if ( empty( $node->meta['menu_title'] ) ) {
|
||||
$this->_render_group( $group, false );
|
||||
} else {
|
||||
$this->_render_group( $group, $node->meta['menu_title'] );
|
||||
}
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
|
|
@ -448,6 +448,11 @@ html:lang(he-il) .rtl #wpadminbar * {
|
|||
background: none;
|
||||
}
|
||||
|
||||
#wpadminbar #wp-admin-bar-user-info a {
|
||||
display: grid;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
#wp-admin-bar-user-info .avatar {
|
||||
position: absolute;
|
||||
right: -72px;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -447,6 +447,11 @@ html:lang(he-il) .rtl #wpadminbar * {
|
|||
background: none;
|
||||
}
|
||||
|
||||
#wpadminbar #wp-admin-bar-user-info a {
|
||||
display: grid;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
#wp-admin-bar-user-info .avatar {
|
||||
position: absolute;
|
||||
left: -72px;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -31,7 +31,7 @@
|
|||
|
||||
topMenuItems = adminBar.querySelectorAll( 'li.menupop' );
|
||||
allMenuItems = adminBar.querySelectorAll( '.ab-item' );
|
||||
adminBarLogout = document.getElementById( 'wp-admin-bar-logout' );
|
||||
adminBarLogout = document.querySelector( '#wp-admin-bar-logout a' );
|
||||
adminBarSearchForm = document.getElementById( 'adminbarsearch' );
|
||||
shortlink = document.getElementById( 'wp-admin-bar-get-shortlink' );
|
||||
skipLink = adminBar.querySelector( '.screen-reader-shortcut' );
|
||||
|
@ -149,7 +149,8 @@
|
|||
function toggleHoverIfEnter( event ) {
|
||||
var wrapper;
|
||||
|
||||
if ( event.which !== 13 ) {
|
||||
// Follow link if pressing Ctrl and/or Shift with Enter (opening in a new tab or window).
|
||||
if ( event.which !== 13 || event.ctrlKey || event.shiftKey ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -336,6 +337,11 @@
|
|||
|
||||
element.className += className;
|
||||
}
|
||||
|
||||
var menuItemToggle = element.querySelector( 'a' );
|
||||
if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
|
||||
menuItemToggle.setAttribute( 'aria-expanded', 'true' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -366,6 +372,11 @@
|
|||
|
||||
element.className = classes.replace( /^[\s]+|[\s]+$/g, '' );
|
||||
}
|
||||
|
||||
var menuItemToggle = element.querySelector( 'a' );
|
||||
if ( className === 'hover' && menuItemToggle && menuItemToggle.hasAttribute( 'aria-expanded' ) ) {
|
||||
menuItemToggle.setAttribute( 'aria-expanded', 'false' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
/*! This file is auto-generated */
|
||||
!function(l,u,d){function m(e){27===e.which&&(e=w(e.target,".menupop"))&&(e.querySelector(".menupop > .ab-item").focus(),y(e,"hover"))}function f(e){var t;13!==e.which||w(e.target,".ab-sub-wrapper")||(t=w(e.target,".menupop"))&&(e.preventDefault(),(o(t,"hover")?y:b)(t,"hover"))}function p(e){var t;13===e.which&&(t=e.target.getAttribute("href"),-1<d.userAgent.toLowerCase().indexOf("applewebkit"))&&t&&"#"===t.charAt(0)&&setTimeout(function(){var e=l.getElementById(t.replace("#",""));e&&(e.setAttribute("tabIndex","0"),e.focus())},100)}function h(e,t){!w(t.target,".ab-sub-wrapper")&&(t.preventDefault(),t=w(t.target,".menupop"))&&(o(t,"hover")?y:(E(e),b))(t,"hover")}function v(e){var t,n=e.target.parentNode;if(t=n?n.querySelector(".shortlink-input"):t)return e.preventDefault&&e.preventDefault(),e.returnValue=!1,b(n,"selected"),t.focus(),t.select(),!(t.onblur=function(){y(n,"selected")})}function g(){if("sessionStorage"in u)try{for(var e in sessionStorage)-1<e.indexOf("wp-autosave-")&&sessionStorage.removeItem(e)}catch(e){}}function o(e,t){return e&&(e.classList&&e.classList.contains?e.classList.contains(t):e.className&&-1<e.className.split(" ").indexOf(t))}function b(e,t){e&&(e.classList&&e.classList.add?e.classList.add(t):o(e,t)||(e.className&&(e.className+=" "),e.className+=t))}function y(e,t){var n,r;if(e&&o(e,t))if(e.classList&&e.classList.remove)e.classList.remove(t);else{for(n=" "+t+" ",r=" "+e.className+" ";-1<r.indexOf(n);)r=r.replace(n,"");e.className=r.replace(/^[\s]+|[\s]+$/g,"")}}function E(e){if(e&&e.length)for(var t=0;t<e.length;t++)y(e[t],"hover")}function L(e){if(!e.target||"wpadminbar"===e.target.id||"wp-admin-bar-top-secondary"===e.target.id)try{u.scrollTo({top:-32,left:0,behavior:"smooth"})}catch(e){u.scrollTo(0,-32)}}function w(e,t){for(u.Element.prototype.matches||(u.Element.prototype.matches=u.Element.prototype.matchesSelector||u.Element.prototype.mozMatchesSelector||u.Element.prototype.msMatchesSelector||u.Element.prototype.oMatchesSelector||u.Element.prototype.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),n=t.length;0<=--n&&t.item(n)!==this;);return-1<n});e&&e!==l;e=e.parentNode)if(e.matches(t))return e;return null}l.addEventListener("DOMContentLoaded",function(){var n,e,t,r,o,a,s,i,c=l.getElementById("wpadminbar");if(c&&"querySelectorAll"in c){n=c.querySelectorAll("li.menupop"),e=c.querySelectorAll(".ab-item"),t=l.getElementById("wp-admin-bar-logout"),r=l.getElementById("adminbarsearch"),o=l.getElementById("wp-admin-bar-get-shortlink"),a=c.querySelector(".screen-reader-shortcut"),s=/Mobile\/.+Safari/.test(d.userAgent)?"touchstart":"click",y(c,"nojs"),"ontouchstart"in u&&(l.body.addEventListener(s,function(e){w(e.target,"li.menupop")||E(n)}),c.addEventListener("touchstart",function e(){for(var t=0;t<n.length;t++)n[t].addEventListener("click",h.bind(null,n));c.removeEventListener("touchstart",e)})),c.addEventListener("click",L);for(i=0;i<n.length;i++)u.hoverintent(n[i],b.bind(null,n[i],"hover"),y.bind(null,n[i],"hover")).options({timeout:180}),n[i].addEventListener("keydown",f);for(i=0;i<e.length;i++)e[i].addEventListener("keydown",m);r&&((s=l.getElementById("adminbar-search")).addEventListener("focus",function(){b(r,"adminbar-focused")}),s.addEventListener("blur",function(){y(r,"adminbar-focused")})),a&&a.addEventListener("keydown",p),o&&o.addEventListener("click",v),u.location.hash&&u.scrollBy(0,-32),t&&t.addEventListener("click",g)}})}(document,window,navigator);
|
||||
!function(l,u,d){function f(e){27===e.which&&(e=w(e.target,".menupop"))&&(e.querySelector(".menupop > .ab-item").focus(),y(e,"hover"))}function p(e){var t;13!==e.which||e.ctrlKey||e.shiftKey||w(e.target,".ab-sub-wrapper")||(t=w(e.target,".menupop"))&&(e.preventDefault(),(a(t,"hover")?y:g)(t,"hover"))}function h(e){var t;13===e.which&&(t=e.target.getAttribute("href"),-1<d.userAgent.toLowerCase().indexOf("applewebkit"))&&t&&"#"===t.charAt(0)&&setTimeout(function(){var e=l.getElementById(t.replace("#",""));e&&(e.setAttribute("tabIndex","0"),e.focus())},100)}function m(e,t){!w(t.target,".ab-sub-wrapper")&&(t.preventDefault(),t=w(t.target,".menupop"))&&(a(t,"hover")?y:(E(e),g))(t,"hover")}function v(e){var t,r=e.target.parentNode;if(t=r?r.querySelector(".shortlink-input"):t)return e.preventDefault&&e.preventDefault(),e.returnValue=!1,g(r,"selected"),t.focus(),t.select(),!(t.onblur=function(){y(r,"selected")})}function b(){if("sessionStorage"in u)try{for(var e in sessionStorage)-1<e.indexOf("wp-autosave-")&&sessionStorage.removeItem(e)}catch(e){}}function a(e,t){return e&&(e.classList&&e.classList.contains?e.classList.contains(t):e.className&&-1<e.className.split(" ").indexOf(t))}function g(e,t){e&&(e.classList&&e.classList.add?e.classList.add(t):a(e,t)||(e.className&&(e.className+=" "),e.className+=t),e=e.querySelector("a"),"hover"===t)&&e&&e.hasAttribute("aria-expanded")&&e.setAttribute("aria-expanded","true")}function y(e,t){var r,n;if(e&&a(e,t)){if(e.classList&&e.classList.remove)e.classList.remove(t);else{for(r=" "+t+" ",n=" "+e.className+" ";-1<n.indexOf(r);)n=n.replace(r,"");e.className=n.replace(/^[\s]+|[\s]+$/g,"")}e=e.querySelector("a");"hover"===t&&e&&e.hasAttribute("aria-expanded")&&e.setAttribute("aria-expanded","false")}}function E(e){if(e&&e.length)for(var t=0;t<e.length;t++)y(e[t],"hover")}function L(e){if(!e.target||"wpadminbar"===e.target.id||"wp-admin-bar-top-secondary"===e.target.id)try{u.scrollTo({top:-32,left:0,behavior:"smooth"})}catch(e){u.scrollTo(0,-32)}}function w(e,t){for(u.Element.prototype.matches||(u.Element.prototype.matches=u.Element.prototype.matchesSelector||u.Element.prototype.mozMatchesSelector||u.Element.prototype.msMatchesSelector||u.Element.prototype.oMatchesSelector||u.Element.prototype.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),r=t.length;0<=--r&&t.item(r)!==this;);return-1<r});e&&e!==l;e=e.parentNode)if(e.matches(t))return e;return null}l.addEventListener("DOMContentLoaded",function(){var r,e,t,n,a,o,s,i,c=l.getElementById("wpadminbar");if(c&&"querySelectorAll"in c){r=c.querySelectorAll("li.menupop"),e=c.querySelectorAll(".ab-item"),t=l.querySelector("#wp-admin-bar-logout a"),n=l.getElementById("adminbarsearch"),a=l.getElementById("wp-admin-bar-get-shortlink"),o=c.querySelector(".screen-reader-shortcut"),s=/Mobile\/.+Safari/.test(d.userAgent)?"touchstart":"click",y(c,"nojs"),"ontouchstart"in u&&(l.body.addEventListener(s,function(e){w(e.target,"li.menupop")||E(r)}),c.addEventListener("touchstart",function e(){for(var t=0;t<r.length;t++)r[t].addEventListener("click",m.bind(null,r));c.removeEventListener("touchstart",e)})),c.addEventListener("click",L);for(i=0;i<r.length;i++)u.hoverintent(r[i],g.bind(null,r[i],"hover"),y.bind(null,r[i],"hover")).options({timeout:180}),r[i].addEventListener("keydown",p);for(i=0;i<e.length;i++)e[i].addEventListener("keydown",f);n&&((s=l.getElementById("adminbar-search")).addEventListener("focus",function(){g(n,"adminbar-focused")}),s.addEventListener("blur",function(){y(n,"adminbar-focused")})),o&&o.addEventListener("keydown",h),a&&a.addEventListener("click",v),u.location.hash&&u.scrollBy(0,-32),t&&t.addEventListener("click",b)}})}(document,window,navigator);
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '6.5-beta2-57707';
|
||||
$wp_version = '6.5-beta2-57708';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue