Twenty Nineteen: Improve menu semantics and keyboard navigation.

The menu's original markup included some non-semantic tags and an unnecessary `tabindex` attribute that made it difficult to navigate via keyboard. 

Props allancole, anevins, kjellr.
Fixes #45713.


Built from https://develop.svn.wordpress.org/trunk@44376


git-svn-id: http://core.svn.wordpress.org/trunk@44206 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
laurelfulford 2018-12-31 17:49:50 +00:00
parent b1c340ef5d
commit fcc423097c
7 changed files with 133 additions and 15 deletions

View File

@ -203,18 +203,18 @@ function twentynineteen_add_ellipses_to_nav( $nav_menu, $args ) {
if ( 'menu-1' === $args->theme_location ) : if ( 'menu-1' === $args->theme_location ) :
$nav_menu .= '<div class="main-menu-more">'; $nav_menu .= '<div class="main-menu-more">';
$nav_menu .= '<ul class="main-menu" tabindex="0">'; $nav_menu .= '<ul class="main-menu">';
$nav_menu .= '<li class="menu-item menu-item-has-children">'; $nav_menu .= '<li class="menu-item menu-item-has-children">';
$nav_menu .= '<a href="#" class="screen-reader-text" aria-label="More" aria-haspopup="true" aria-expanded="false">' . esc_html__( 'More', 'twentynineteen' ) . '</a>'; $nav_menu .= '<button class="submenu-expand main-menu-more-toggle is-empty" tabindex="-1" aria-label="More" aria-haspopup="true" aria-expanded="false">';
$nav_menu .= '<span class="submenu-expand main-menu-more-toggle is-empty" tabindex="-1">'; $nav_menu .= '<span class="screen-reader-text">' . esc_html__( 'More', 'twentynineteen' ) . '</span>';
$nav_menu .= twentynineteen_get_icon_svg( 'arrow_drop_down_ellipsis' ); $nav_menu .= twentynineteen_get_icon_svg( 'arrow_drop_down_ellipsis' );
$nav_menu .= '</span>'; $nav_menu .= '</button>';
$nav_menu .= '<ul class="sub-menu hidden-links">'; $nav_menu .= '<ul class="sub-menu hidden-links">';
$nav_menu .= '<li id="menu-item--1" class="mobile-parent-nav-menu-item menu-item--1">'; $nav_menu .= '<li id="menu-item--1" class="mobile-parent-nav-menu-item menu-item--1">';
$nav_menu .= '<span class="menu-item-link-return">'; $nav_menu .= '<button class="menu-item-link-return">';
$nav_menu .= twentynineteen_get_icon_svg( 'chevron_left' ); $nav_menu .= twentynineteen_get_icon_svg( 'chevron_left' );
$nav_menu .= esc_html__( 'Back', 'twentynineteen' ); $nav_menu .= esc_html__( 'Back', 'twentynineteen' );
$nav_menu .= '</span>'; $nav_menu .= '</button>';
$nav_menu .= '</li>'; $nav_menu .= '</li>';
$nav_menu .= '</ul>'; $nav_menu .= '</ul>';
$nav_menu .= '</li>'; $nav_menu .= '</li>';
@ -269,11 +269,11 @@ function twentynineteen_add_dropdown_icons( $output, $item, $depth, $args ) {
// Inject the keyboard_arrow_left SVG inside the parent nav menu item, and let the item link to the parent item. // Inject the keyboard_arrow_left SVG inside the parent nav menu item, and let the item link to the parent item.
// @todo Only do this for nested submenus? If on a first-level submenu, then really the link could be "#" since the desire is to remove the target entirely. // @todo Only do this for nested submenus? If on a first-level submenu, then really the link could be "#" since the desire is to remove the target entirely.
$link = sprintf( $link = sprintf(
'<span class="menu-item-link-return" tabindex="-1">%s', '<button class="menu-item-link-return" tabindex="-1">%s',
twentynineteen_get_icon_svg( 'chevron_left', 24 ) twentynineteen_get_icon_svg( 'chevron_left', 24 )
); );
// replace opening <a> with <span> // replace opening <a> with <button>
$output = preg_replace( $output = preg_replace(
'/<a\s.*?>/', '/<a\s.*?>/',
$link, $link,
@ -281,10 +281,10 @@ function twentynineteen_add_dropdown_icons( $output, $item, $depth, $args ) {
1 // Limit. 1 // Limit.
); );
// replace closing </a> with </span> // replace closing </a> with </button>
$output = preg_replace( $output = preg_replace(
'#</a>#i', '#</a>#i',
'</span>', '</button>',
$output, $output,
1 // Limit. 1 // Limit.
); );
@ -295,7 +295,7 @@ function twentynineteen_add_dropdown_icons( $output, $item, $depth, $args ) {
$icon = twentynineteen_get_icon_svg( 'keyboard_arrow_down', 24 ); $icon = twentynineteen_get_icon_svg( 'keyboard_arrow_down', 24 );
$output .= sprintf( $output .= sprintf(
'<span class="submenu-expand" tabindex="-1">%s</span>', '<button class="submenu-expand" tabindex="-1">%s</button>',
$icon $icon
); );
} }

View File

@ -112,7 +112,7 @@
currentSubMenu.parentElement.lastElementChild.className += ' expanded-true'; currentSubMenu.parentElement.lastElementChild.className += ' expanded-true';
// Update aria-expanded state // Update aria-expanded state
toggleAriaExpandedState( currentSubMenu.previousSibling ); toggleAriaExpandedState( currentSubMenu );
} }
/** /**
@ -230,7 +230,8 @@
openSubMenu(event.target); openSubMenu(event.target);
// Check if child of .submenu-expand is touched // Check if child of .submenu-expand is touched
} else if ( null != getCurrentParent( event.target, '.submenu-expand' ) && getCurrentParent( event.target, '.submenu-expand' ).matches( '.submenu-expand' ) ) { } else if ( null != getCurrentParent( event.target, '.submenu-expand' ) &&
getCurrentParent( event.target, '.submenu-expand' ).matches( '.submenu-expand' ) ) {
openSubMenu( getCurrentParent( event.target, '.submenu-expand' ) ); openSubMenu( getCurrentParent( event.target, '.submenu-expand' ) );
// Check if .menu-item-link-return is touched // Check if .menu-item-link-return is touched
@ -254,6 +255,7 @@
if ( null != mainNav && hasClass( mainNav, '.main-navigation' ) ) { if ( null != mainNav && hasClass( mainNav, '.main-navigation' ) ) {
// Prevent default mouse events // Prevent default mouse events
event.preventDefault(); event.preventDefault();
} else if ( } else if (
event.target.matches('.submenu-expand') || event.target.matches('.submenu-expand') ||
null != getCurrentParent( event.target, '.submenu-expand' ) && null != getCurrentParent( event.target, '.submenu-expand' ) &&

View File

@ -13,6 +13,39 @@
display: inline; display: inline;
} }
/* Un-style buttons */
button {
display: inline-block;
border: none;
padding: 0;
margin: 0;
font-family: $font__heading;
font-weight: 700;
line-height: $font__line-height-heading;
text-decoration: none;
background: transparent;
color: inherit;
cursor: pointer;
transition: background 250ms ease-in-out,
transform 150ms ease;
-webkit-appearance: none;
-moz-appearance: none;
&:hover,
&:focus {
background: transparent;
}
&:focus {
outline: 1px solid transparent;
outline-offset: -4px;
}
&:active {
transform: scale(0.99);
}
}
.main-menu { .main-menu {
display: inline-block; display: inline-block;
@ -183,6 +216,13 @@
} }
} }
> .menu-item-link-return {
width: 100%;
font-size: $font__size_base;
font-weight: normal;
text-align: left;
}
> a:empty { > a:empty {
display: none; display: none;
} }

View File

@ -1027,6 +1027,7 @@ a:focus {
.main-navigation { .main-navigation {
display: block; display: block;
margin-top: 0.25rem; margin-top: 0.25rem;
/* Un-style buttons */
/* /*
* Sub-menu styles * Sub-menu styles
* *
@ -1049,6 +1050,36 @@ body.page .main-navigation {
display: inline; display: inline;
} }
.main-navigation button {
display: inline-block;
border: none;
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-weight: 700;
line-height: 1.2;
text-decoration: none;
background: transparent;
color: inherit;
cursor: pointer;
transition: background 250ms ease-in-out, transform 150ms ease;
-webkit-appearance: none;
-moz-appearance: none;
}
.main-navigation button:hover, .main-navigation button:focus {
background: transparent;
}
.main-navigation button:focus {
outline: 1px solid transparent;
outline-offset: -4px;
}
.main-navigation button:active {
transform: scale(0.99);
}
.main-navigation .main-menu { .main-navigation .main-menu {
display: inline-block; display: inline-block;
margin: 0; margin: 0;
@ -1207,6 +1238,13 @@ body.page .main-navigation {
background: #005177; background: #005177;
} }
.main-navigation .sub-menu > li > .menu-item-link-return {
width: 100%;
font-size: 22px;
font-weight: normal;
text-align: right;
}
.main-navigation .sub-menu > li > a:empty { .main-navigation .sub-menu > li > a:empty {
display: none; display: none;
} }

View File

@ -1027,6 +1027,7 @@ a:focus {
.main-navigation { .main-navigation {
display: block; display: block;
margin-top: 0.25rem; margin-top: 0.25rem;
/* Un-style buttons */
/* /*
* Sub-menu styles * Sub-menu styles
* *
@ -1049,6 +1050,36 @@ body.page .main-navigation {
display: inline; display: inline;
} }
.main-navigation button {
display: inline-block;
border: none;
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-weight: 700;
line-height: 1.2;
text-decoration: none;
background: transparent;
color: inherit;
cursor: pointer;
transition: background 250ms ease-in-out, transform 150ms ease;
-webkit-appearance: none;
-moz-appearance: none;
}
.main-navigation button:hover, .main-navigation button:focus {
background: transparent;
}
.main-navigation button:focus {
outline: 1px solid transparent;
outline-offset: -4px;
}
.main-navigation button:active {
transform: scale(0.99);
}
.main-navigation .main-menu { .main-navigation .main-menu {
display: inline-block; display: inline-block;
margin: 0; margin: 0;
@ -1207,6 +1238,13 @@ body.page .main-navigation {
background: #005177; background: #005177;
} }
.main-navigation .sub-menu > li > .menu-item-link-return {
width: 100%;
font-size: 22px;
font-weight: normal;
text-align: left;
}
.main-navigation .sub-menu > li > a:empty { .main-navigation .sub-menu > li > a:empty {
display: none; display: none;
} }

View File

@ -36,7 +36,7 @@
array( array(
'theme_location' => 'menu-1', 'theme_location' => 'menu-1',
'menu_class' => 'main-menu', 'menu_class' => 'main-menu',
'items_wrap' => '<ul id="%1$s" class="%2$s" tabindex="0">%3$s</ul>', 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
) )
); );
?> ?>

View File

@ -13,7 +13,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '5.1-alpha-44375'; $wp_version = '5.1-alpha-44376';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.