Make WordPress Core

Changeset 61764


Ignore:
Timestamp:
02/27/2026 10:48:36 PM (8 months ago)
Author:
joedolson
Message:

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.

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/link.js

    r50547 r61764  
    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') )
  • trunk/src/js/_enqueues/admin/post.js

    r59454 r61764  
    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                });
  • trunk/src/wp-admin/includes/meta-boxes.php

    r61651 r61764  
    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 ); ?>
    … …  
    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 . ']';
    … …  
    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
    … …  
    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' ); ?>
Note: See TracChangeset for help on using the changeset viewer.