Administration: Ensure collapse menu is usable with a keyboard

Currently, the "Collapse menu" item is not focusable and keyboard users can't collapse/expand the admin menu. This aims to fix it so that screen readers no longer announce it as a clickable but it remains unfocusable and thus unusable. So it's now a button.

Quoting joedolson at WordCamp Chicago 2014:
"If it's supposed to act like a button, it should be a button."

Also includes a grunt:precommit run that picked up some postcss changes to src/wp-includes/css/customize-preview.css

Fixes #29958.
Props ajercia, ipm-frommen for an iterative patch, valendesigns for an iterative patch, GaryJ for feedback, joedolson for feedback, helen for feedback




git-svn-id: https://develop.svn.wordpress.org/trunk@39141 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Aaron Jorbin
2016-11-04 16:01:24 +00:00
parent f7e5811287
commit 9768ec2b97
6 changed files with 265 additions and 107 deletions
+53 -54
View File
@@ -264,7 +264,7 @@
.folded #adminmenu .wp-has-current-submenu.opensub .wp-submenu,
.folded #adminmenu a.menu-top:focus + .wp-submenu,
.folded #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu,
.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu {
.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu {
top: 0;
left: 36px;
}
@@ -547,79 +547,82 @@ ul#adminmenu > li.current > a.current:after {
display: none;
}
#collapse-menu {
font-size: 13px;
#collapse-button {
display: block;
width: 100%;
height: 34px;
margin: 0;
border: none;
padding: 0;
position: relative;
overflow: visible;
line-height: 34px;
margin-top: 10px;
color: #a0a5aa;
color: rgba(240,245,250,0.6);
-webkit-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
background: none;
color: #aaa;
cursor: pointer;
outline: 0;
}
#collapse-menu:hover,
#collapse-menu:hover #collapse-button div:after {
#collapse-button:hover,
#collapse-button:focus {
color: #00b9eb;
}
.folded #collapse-menu span {
#collapse-button .collapse-button-icon,
#collapse-button .collapse-button-label {
/* absolutely positioned to avoid 1px shift in IE when button is pressed */
display: block;
position: absolute;
top: 0;
left: 0;
line-height: 34px;
}
#collapse-button .collapse-button-icon {
width: 36px;
height: 34px;
}
#collapse-button .collapse-button-label {
padding: 0 0 0 36px;
}
.folded #collapse-button .collapse-button-label {
display: none;
}
#collapse-button,
#collapse-button div {
width: 15px;
height: 15px;
}
#collapse-button {
float: left;
height: 15px;
margin: 10px 8px 10px 11px;
width: 15px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
#wpwrap #collapse-button div {
padding: 0;
}
#collapse-button div:after {
#collapse-button .collapse-button-icon:after {
content: "\f148";
display: block;
line-height: 15px;
left: -3px;
top: -3px;
color: #a0a5aa;
color: rgba(240,245,250,0.6);
position: relative;
top: 7px;
text-align: center;
font: normal 20px/1 dashicons !important;
speak: none;
margin: 0 auto;
padding: 0 !important;
position: relative;
text-align: center;
width: 20px;
-webkit-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* rtl:ignore */
.folded #collapse-button div:after,
.rtl #collapse-button div:after {
.folded #collapse-button .collapse-button-icon:after,
.rtl #collapse-button .collapse-button-icon:after {
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.rtl.folded #collapse-button div:after {
.rtl.folded #collapse-button .collapse-button-icon:after {
-webkit-transform: none;
-ms-transform: none;
transform: none;
}
#collapse-button .collapse-button-icon:after,
#collapse-button .collapse-button-label {
-webkit-transition: all .1s ease-in-out;
transition: all .1s ease-in-out;
}
/**
* Toolbar menu toggle
*/
@@ -652,7 +655,7 @@ li#wp-admin-bar-menu-toggle {
.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu.sub-open,
.auto-fold #adminmenu .wp-has-current-submenu.opensub .wp-submenu,
.auto-fold #adminmenu a.menu-top:focus + .wp-submenu,
.auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu {
.auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu {
top: 0px;
left: 36px;
}
@@ -731,22 +734,18 @@ li#wp-admin-bar-menu-toggle {
z-index: 10000;
}
.auto-fold #collapse-menu span {
.auto-fold #collapse-menu .collapse-button-label {
display: none;
}
.auto-fold #collapse-button div {
background: none;
}
/* rtl:ignore */
.auto-fold #collapse-button div:after {
.auto-fold #collapse-button .collapse-button-icon:after {
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.rtl.auto-fold #collapse-button div:after {
.rtl.auto-fold #collapse-button .collapse-button-icon:after {
-webkit-transform: none;
-ms-transform: none;
transform: none;
+4 -12
View File
@@ -227,23 +227,15 @@ ul#adminmenu > li.current > a.current:after {
/* Admin Menu: collapse button */
#collapse-menu {
#collapse-button {
color: $menu-collapse-text;
}
#collapse-menu:hover {
color: $menu-collapse-focus-text;
#collapse-button:hover,
#collapse-button:focus {
color: $menu-submenu-focus-text;
}
#collapse-button div:after {
color: $menu-collapse-icon;
}
#collapse-menu:hover #collapse-button div:after {
color: $menu-collapse-focus-icon;
}
/* Admin Bar */
#wpadminbar {
+91 -35
View File
@@ -196,6 +196,7 @@ $document.ready( function() {
pinnedMenuTop = false,
pinnedMenuBottom = false,
menuTop = 0,
menuState,
menuIsPinned = false,
height = {
window: $window.height(),
@@ -211,59 +212,43 @@ $document.ready( function() {
$(e.target).parent().siblings('a').get(0).click();
});
$('#collapse-menu').on('click.collapse-menu', function() {
var respWidth, state;
$( '#collapse-button' ).on( 'click.collapse-menu', function() {
var viewportWidth = getViewportWidth() || 961;
// reset any compensation for submenus near the bottom of the screen
$('#adminmenu div.wp-submenu').css('margin-top', '');
if ( window.innerWidth ) {
// window.innerWidth is affected by zooming on phones
respWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
} else {
// IE < 9 doesn't support @media CSS rules
respWidth = 961;
}
if ( respWidth && respWidth < 960 ) {
if ( viewportWidth < 960 ) {
if ( $body.hasClass('auto-fold') ) {
$body.removeClass('auto-fold').removeClass('folded');
setUserSetting('unfold', 1);
setUserSetting('mfold', 'o');
state = 'open';
menuState = 'open';
} else {
$body.addClass('auto-fold');
setUserSetting('unfold', 0);
state = 'folded';
menuState = 'folded';
}
} else {
if ( $body.hasClass('folded') ) {
$body.removeClass('folded');
setUserSetting('mfold', 'o');
state = 'open';
menuState = 'open';
} else {
$body.addClass('folded');
setUserSetting('mfold', 'f');
state = 'folded';
menuState = 'folded';
}
}
currentMenuItemHasPopup();
$document.trigger( 'wp-collapse-menu', { state: state } );
$document.trigger( 'wp-collapse-menu', { state: menuState } );
});
// Handle the `aria-haspopup` attribute on the current menu item when it has a sub-menu.
function currentMenuItemHasPopup() {
var respWidth,
$current = $( 'a.wp-has-current-submenu' );
var $current = $( 'a.wp-has-current-submenu' );
if ( window.innerWidth ) {
respWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
} else {
respWidth = 961;
}
if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && respWidth && respWidth <= 960 && respWidth > 782 ) ) {
if ( 'folded' === menuState ) {
// When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu.
$current.attr( 'aria-haspopup', 'true' );
} else {
@@ -272,7 +257,7 @@ $document.ready( function() {
}
}
$document.on( 'wp-window-resized wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
$document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
/**
* Ensure an admin submenu is within the visual viewport.
@@ -836,17 +821,14 @@ $document.ready( function() {
},
trigger: function() {
var width;
var viewportWidth = getViewportWidth();
if ( window.innerWidth ) {
// window.innerWidth is affected by zooming on phones
width = Math.max( window.innerWidth, document.documentElement.clientWidth );
} else {
// Exclude IE < 9, it doesn't support @media CSS rules
// Exclude IE < 9, it doesn't support @media CSS rules.
if ( ! viewportWidth ) {
return;
}
if ( width <= 782 ) {
if ( viewportWidth <= 782 ) {
if ( ! wpResponsiveActive ) {
$document.trigger( 'wp-responsive-activate' );
wpResponsiveActive = true;
@@ -858,7 +840,7 @@ $document.ready( function() {
}
}
if ( width <= 480 ) {
if ( viewportWidth <= 480 ) {
this.enableOverlay();
} else {
this.disableOverlay();
@@ -912,8 +894,82 @@ $document.ready( function() {
aria_button_if_js();
});
/**
* @summary Get the viewport width.
*
* @since 4.7
*
* @returns {number|boolean} The current viewport width or false if the
* browser doesn't support innerWidth (IE < 9).
*/
function getViewportWidth() {
var viewportWidth = false;
if ( window.innerWidth ) {
// On phones, window.innerWidth is affected by zooming.
viewportWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
}
return viewportWidth;
}
/**
* @summary Set the admin menu collapsed/expanded state.
*
* Sets the global variable `menuState` and triggers a custom event passing
* the current menu state.
*
* @since 4.7
*
* @returns {void}
*/
function setMenuState() {
var viewportWidth = getViewportWidth() || 961;
if ( viewportWidth <= 782 ) {
menuState = 'responsive';
} else if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && viewportWidth <= 960 && viewportWidth > 782 ) ) {
menuState = 'folded';
} else {
menuState = 'open';
}
$document.trigger( 'wp-menu-state-set', { state: menuState } );
}
// Set the menu state when the window gets resized.
$document.on( 'wp-window-resized.set-menu-state', setMenuState );
/**
* @summary Set ARIA attributes on the collapse/expand menu button.
*
* When the admin menu is open or folded, updates the `aria-expanded` and
* `aria-label` attributes of the button to give feedback to assistive
* technologies. In the responsive view, the button is always hidden.
*
* @since 4.7
*
* @returns {void}
*/
$document.on( 'wp-menu-state-set wp-collapse-menu', function( event, eventData ) {
var $collapseButton = $( '#collapse-button' ),
ariaExpanded = 'true',
ariaLabelText = commonL10n.collapseMenu;
if ( 'folded' === eventData.state ) {
ariaExpanded = 'false';
ariaLabelText = commonL10n.expandMenu;
}
$collapseButton.attr({
'aria-expanded': ariaExpanded,
'aria-label': ariaLabelText
});
});
window.wpResponsive.init();
setPinMenu();
setMenuState();
currentMenuItemHasPopup();
makeNoticesDismissible();
aria_button_if_js();
+5 -3
View File
@@ -234,9 +234,11 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) {
echo "</li>";
}
echo '<li id="collapse-menu" class="hide-if-no-js"><div id="collapse-button"><div></div></div>';
echo '<span>' . esc_html__( 'Collapse menu' ) . '</span>';
echo '</li>';
echo '<li id="collapse-menu" class="hide-if-no-js">' .
'<button type="button" id="collapse-button" aria-label="' . esc_attr__( 'Collapse Main menu' ) . '" aria-expanded="true">' .
'<span class="collapse-button-icon" aria-hidden="true"></span>' .
'<span class="collapse-button-label">' . __( 'Collapse menu' ) . '</span>' .
'</button></li>';
}
?>