Skip to content

Commit 588a02f

Browse files
committed
Editor: A11y: Use a tablist pattern for taxonomy terms.
Switch the classic editor's taxonomy tabs to use the APG tablist/tabpanel structure. Add appropriate ARIA roles to tabs and panels and update JS to handle required keyboard events and selected states. Props alh0319, mukesh27, joedolson. Fixes #63981. git-svn-id: https://develop.svn.wordpress.org/trunk@61764 602fd350-edb4-49c9-b593-d223f7449a82
1 parent a915060 commit 588a02f

3 files changed

Lines changed: 68 additions & 28 deletions

File tree

src/js/_enqueues/admin/link.js

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,37 @@ jQuery( function($) {
1919
*
2020
* @return {boolean} Always returns false to prevent the default behavior.
2121
*/
22-
$('#category-tabs a').on( 'click', function(){
22+
$('#category-tabs a').on( 'click keyup keydown', function( event ){
2323
var t = $(this).attr('href');
24-
$(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
25-
$('.tabs-panel').hide();
26-
$(t).show();
27-
if ( '#categories-all' == t )
28-
deleteUserSetting('cats');
29-
else
30-
setUserSetting('cats','pop');
31-
return false;
24+
if ( event.type === 'keydown' && event.key === ' ' ) {
25+
event.preventDefault();
26+
}
27+
if ( ( event.type === 'keyup' && event.key === ' ' ) || ( event.type === 'keydown' && event.key === 'Enter' ) || event.type === 'click' ) {
28+
event.preventDefault();
29+
$('#category-tabs a').removeAttr( 'aria-selected' ).attr( 'tabindex', '-1' );
30+
$(this).attr( 'aria-selected', 'true' ).removeAttr( 'tabindex' );
31+
$(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
32+
$('.tabs-panel').hide();
33+
$(t).show();
34+
if ( '#categories-all' == t ) {
35+
deleteUserSetting('cats');
36+
} else {
37+
setUserSetting('cats','pop');
38+
}
39+
return false;
40+
}
41+
if ( event.type === 'keyup' && ( event.key === 'ArrowRight' || event.key === 'ArrowLeft' ) ) {
42+
$(this).attr( 'tabindex', '-1' );
43+
let next = $(this).parent('li').next();
44+
let prev = $(this).parent('li').prev();
45+
if ( next.length > 0 ) {
46+
next.find('a').removeAttr( 'tabindex');
47+
next.find('a').trigger( 'focus' );
48+
} else {
49+
prev.find('a').removeAttr( 'tabindex');
50+
prev.find('a').trigger( 'focus' );
51+
}
52+
}
3253
});
3354
if ( getUserSetting('cats') )
3455
$('#category-tabs a[href="#categories-pop"]').trigger( 'click' );

src/js/_enqueues/admin/post.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -566,16 +566,35 @@ jQuery( function($) {
566566
}
567567

568568
// @todo Move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js.
569-
$('a', '#' + taxonomy + '-tabs').on( 'click', function( e ) {
570-
e.preventDefault();
569+
$('a', '#' + taxonomy + '-tabs').on( 'click keyup keydown', function( event ) {
571570
var t = $(this).attr('href');
572-
$(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
573-
$('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide();
574-
$(t).show();
575-
if ( '#' + taxonomy + '-all' == t ) {
576-
deleteUserSetting( settingName );
577-
} else {
578-
setUserSetting( settingName, 'pop' );
571+
if ( event.type === 'keydown' && event.key === ' ' ) {
572+
event.preventDefault();
573+
}
574+
if ( ( event.type === 'keyup' && event.key === ' ' ) || ( event.type === 'keydown' && event.key === 'Enter' ) || event.type === 'click' ) {
575+
event.preventDefault();
576+
$('#' + taxonomy + '-tabs a').removeAttr( 'aria-selected' ).attr( 'tabindex', '-1' );
577+
$(this).attr( 'aria-selected', 'true' ).removeAttr( 'tabindex' );
578+
$(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
579+
$('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide();
580+
$(t).show();
581+
if ( '#' + taxonomy + '-all' == t ) {
582+
deleteUserSetting( settingName );
583+
} else {
584+
setUserSetting( settingName, 'pop' );
585+
}
586+
}
587+
if ( event.type === 'keyup' && ( event.key === 'ArrowRight' || event.key === 'ArrowLeft' ) ) {
588+
$(this).attr( 'tabindex', '-1' );
589+
let next = $(this).parent('li').next();
590+
let prev = $(this).parent('li').prev();
591+
if ( next.length > 0 ) {
592+
next.find('a').removeAttr( 'tabindex');
593+
next.find('a').trigger( 'focus' );
594+
} else {
595+
prev.find('a').removeAttr( 'tabindex');
596+
prev.find('a').trigger( 'focus' );
597+
}
579598
}
580599
});
581600

src/wp-admin/includes/meta-boxes.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -644,18 +644,18 @@ function post_categories_meta_box( $post, $box ) {
644644
$taxonomy = get_taxonomy( $parsed_args['taxonomy'] );
645645
?>
646646
<div id="taxonomy-<?php echo $tax_name; ?>" class="categorydiv">
647-
<ul id="<?php echo $tax_name; ?>-tabs" class="category-tabs">
648-
<li class="tabs"><a href="#<?php echo $tax_name; ?>-all"><?php echo $taxonomy->labels->all_items; ?></a></li>
649-
<li class="hide-if-no-js"><a href="#<?php echo $tax_name; ?>-pop"><?php echo esc_html( $taxonomy->labels->most_used ); ?></a></li>
647+
<ul id="<?php echo $tax_name; ?>-tabs" class="category-tabs" role="tablist">
648+
<li class="tabs"><a href="#<?php echo $tax_name; ?>-all" role="tab" aria-selected="true" aria-controls="<?php echo $tax_name; ?>-all"><?php echo $taxonomy->labels->all_items; ?></a></li>
649+
<li class="hide-if-no-js"><a href="#<?php echo $tax_name; ?>-pop" role="tab" aria-controls="<?php echo $tax_name; ?>-pop"><?php echo esc_html( $taxonomy->labels->most_used ); ?></a></li>
650650
</ul>
651651

652-
<div id="<?php echo $tax_name; ?>-pop" class="tabs-panel" style="display: none;">
652+
<div id="<?php echo $tax_name; ?>-pop" class="tabs-panel" style="display: none;" role="tabpanel">
653653
<ul id="<?php echo $tax_name; ?>checklist-pop" class="categorychecklist form-no-clear" >
654654
<?php $popular_ids = wp_popular_terms_checklist( $tax_name ); ?>
655655
</ul>
656656
</div>
657657

658-
<div id="<?php echo $tax_name; ?>-all" class="tabs-panel">
658+
<div id="<?php echo $tax_name; ?>-all" class="tabs-panel" role="tabpanel">
659659
<?php
660660
$name = ( 'category' === $tax_name ) ? 'post_category' : 'tax_input[' . $tax_name . ']';
661661
// Allows for an empty term set to be sent. 0 is an invalid term ID and will be ignored by empty() checks.
@@ -1176,12 +1176,12 @@ function link_submit_meta_box( $link ) {
11761176
function link_categories_meta_box( $link ) {
11771177
?>
11781178
<div id="taxonomy-linkcategory" class="categorydiv">
1179-
<ul id="category-tabs" class="category-tabs">
1180-
<li class="tabs"><a href="#categories-all"><?php _e( 'All categories' ); ?></a></li>
1181-
<li class="hide-if-no-js"><a href="#categories-pop"><?php _ex( 'Most Used', 'categories' ); ?></a></li>
1179+
<ul id="category-tabs" class="category-tabs" role="tablist">
1180+
<li class="tabs"><a href="#categories-all" role="tab" aria-controls="categories-all" aria-selected="true"><?php _e( 'All categories' ); ?></a></li>
1181+
<li class="hide-if-no-js"><a href="#categories-pop" role="tab" aria-controls="categories-pop"><?php _ex( 'Most Used', 'categories' ); ?></a></li>
11821182
</ul>
11831183

1184-
<div id="categories-all" class="tabs-panel">
1184+
<div id="categories-all" class="tabs-panel" role="tabpanel">
11851185
<ul id="categorychecklist" data-wp-lists="list:category" class="categorychecklist form-no-clear">
11861186
<?php
11871187
if ( isset( $link->link_id ) ) {
@@ -1193,7 +1193,7 @@ function link_categories_meta_box( $link ) {
11931193
</ul>
11941194
</div>
11951195

1196-
<div id="categories-pop" class="tabs-panel" style="display: none;">
1196+
<div id="categories-pop" class="tabs-panel" style="display: none;" role="tabpanel">
11971197
<ul id="categorychecklist-pop" class="categorychecklist form-no-clear">
11981198
<?php wp_popular_terms_checklist( 'link_category' ); ?>
11991199
</ul>

0 commit comments

Comments
 (0)