Make WordPress Core

Opened 6 months ago

Closed 11 days ago

#63981 closed defect (bug) (fixed)

Taxonomy meta box tabs not programmatically identified

Reported by: alh0319's profile alh0319 Owned by: joedolson's profile joedolson
Milestone: 7.0 Priority: normal
Severity: normal Version: 2.9
Component: Posts, Post Types Keywords: has-patch commit
Focuses: accessibility Cc:

Description

In the classic editor, when a hierarchical taxonomy is present the metabox for selecting terms has two tabs "All $TaxName" and "Most Used". This is an example of those tabs in the Categories meta box:

Image showing tabs in Categories meta box

Code for this element:

<div id="taxonomy-category" class="categorydiv">
		<ul id="category-tabs" class="category-tabs">
			<li class="tabs"><a href="#category-all">All Categories</a></li>
			<li class="hide-if-no-js"><a href="#category-pop">Most Used</a></li>
		</ul>

		<div id="category-pop" class="tabs-panel" style="display: none;">
			<ul id="categorychecklist-pop" class="categorychecklist form-no-clear">
				
		<li id="popular-category-66" class="popular-category">
			<label class="selectit">
				<input id="in-popular-category-66" type="checkbox" checked="checked" value="66">
				News			</label>
		</li>

					</ul>
		</div>

		<div id="category-all" class="tabs-panel">
			<input type="hidden" name="post_category[]" value="0">			<ul id="categorychecklist" data-wp-lists="list:category" class="categorychecklist form-no-clear">
				
<li id="in-category-66-1" class="popular-category"><label class="selectit"><input value="66" type="checkbox" name="post_category[]" id="in-category-66-2" checked="checked"> News</label></li>

<li id="in-category-1-1"><label class="selectit"><input value="1" type="checkbox" name="post_category[]" id="in-category-1-2"> Uncategorized</label></li>
			</ul>
		</div>
				<div id="category-adder" class="wp-hidden-children">
				<a id="category-add-toggle" href="#category-add" class="hide-if-no-js taxonomy-add-new">
					+ Add Category				</a>
				<p id="category-add" class="category-add wp-hidden-child">
					<label class="screen-reader-text" for="newcategory">Add Category</label>
					<input type="text" name="newcategory" id="newcategory" class="form-required form-input-tip" value="New Category Name" aria-required="true">
					<label class="screen-reader-text" for="newcategory_parent">
						Parent Category:					</label>
					<select name="newcategory_parent" id="newcategory_parent" class="postform">
	<option value="-1">— Parent Category —</option>
	<option class="level-0" value="66">News</option>
	<option class="level-0" value="1">Uncategorized</option>
</select>
					<input type="button" id="category-add-submit" data-wp-lists="add:categorychecklist:category-add" class="button category-add-submit" value="Add Category">
					<input type="hidden" id="_ajax_nonce-add-category" name="_ajax_nonce-add-category" value="c53a523941">					<span id="category-ajax-response"></span>
				</p>
			</div>
			</div>

These tabs are not programmatically defined and don't follow the expected keyboard navigation pattern for tabs. They are announced as links by screen readers. They also don't indicate which tab is currently selected.

Image showing NVDA announcements for the tabs in a custom taxonomy

As currently coded, these tabs fail WCAG 4.1.2 Name, Role, Value

Recommended Fix

The following fixes need to be applied to these tabs. The fixes should work for core Categories and also any custom taxonomies created by plugins/themes, such as WooCommerce product categories and brands.

  1. Add role="tablist" to the container for the tabs.
  2. Add role="tab" to each tab and an aria-controls attribute that links each tab to the ID of the tab panel that it controls.
  3. Add role="tabpanel" to the div that contains the tab contents.
  4. Add aria-selected="true" to the tab for the currently active panel and use JavaScript to change which tab the attribute is on as they are selected.
  5. Only the selected tab should be in the taborder - right and left arrow keys should be used to move between the tabs. The next tab stop after the selected tab should be the first focusable element in the tab panel.
  6. Tabs should be able to be triggered/selected with the space bar and the return/enter key.

For more information refer to: APG Manual Tabs Example

Change History (14)

This ticket was mentioned in Slack in #accessibility by amberhinds. View the logs.


6 months ago

#2 @joedolson
6 months ago

  • Owner set to joedolson
  • Status changed from new to accepted

#3 @joedolson
4 months ago

  • Focuses accessibility added

This ticket was mentioned in Slack in #accessibility by joedolson. View the logs.


4 months ago

#5 @joedolson
4 months ago

  • Milestone changed from Awaiting Review to 7.0
  • Version set to 2.9

Recording this as coming from version 2.9.0, as that's when the category tabs were added. That's not strictly accurate, since the *bug* here is that the tabs don't use appropriate ARIA roles, which didn't exist at the time this was created. But eh, whatever.

This ticket was mentioned in PR #11035 on WordPress/wordpress-develop by @joedolson.


2 weeks ago
#6

  • Keywords has-patch added

The tab list for switching between the term list and frequently used lists in classic editor views needs to be marked up as a list of tabpanels.

Trac ticket: https://core.trac.wordpress.org/ticket/63981

## Use of AI Tools

none

#7 @joedolson
2 weeks ago

No visual changes, but now operates from the keyboard & reports appropriately to screen readers.

@alh0319 commented on PR #11035:


11 days ago
#8

@joedolson I'm having trouble testing this using playground. Here are the steps I've taken:

  1. Load playground for PR 11035.
  2. Install and activate classic editor plugin.
  3. Go to the edit screen for the Hello World blog post.
  4. Inspect the code on the categories metabox.

This is what I see:
https://github.com/user-attachments/assets/6b90cb9f-0652-4a4a-80ce-a49f0e418ad9

<div id="taxonomy-category" class="categorydiv">
		<ul id="category-tabs" class="category-tabs">
			<li class="tabs"><a href="#category-all">All Categories</a></li>
			<li class="hide-if-no-js"><a href="#category-pop">Most Used</a></li>
		</ul>

		<div id="category-pop" class="tabs-panel" style="display: none;">
			<ul id="categorychecklist-pop" class="categorychecklist form-no-clear">
				
		<li id="popular-category-1" class="popular-category">
			<label class="selectit">
				<input id="in-popular-category-1" type="checkbox" checked="checked" value="1">
				Uncategorized			</label>
		</li>

					</ul>
		</div>

		<div id="category-all" class="tabs-panel">
			<input type="hidden" name="post_category[]" value="0">			<ul id="categorychecklist" data-wp-lists="list:category" class="categorychecklist form-no-clear">
				
<li id="in-category-1-1" class="popular-category"><label class="selectit"><input value="1" type="checkbox" name="post_category[]" id="in-category-1-2" checked="checked"> Uncategorized</label></li>
			</ul>
		</div>
				<div id="category-adder" class="wp-hidden-children">
				<a id="category-add-toggle" href="#category-add" class="hide-if-no-js taxonomy-add-new">
					+ Add Category				</a>
				<p id="category-add" class="category-add wp-hidden-child">
					<label class="screen-reader-text" for="newcategory">Add Category</label>
					<input type="text" name="newcategory" id="newcategory" class="form-required form-input-tip" value="New Category Name" aria-required="true">
					<label class="screen-reader-text" for="newcategory_parent">
						Parent Category:					</label>
					<select name="newcategory_parent" id="newcategory_parent" class="postform">
	<option value="-1">— Parent Category —</option>
	<option class="level-0" value="1">Uncategorized</option>
</select>
					<input type="button" id="category-add-submit" data-wp-lists="add:categorychecklist:category-add" class="button category-add-submit" value="Add Category">
					<input type="hidden" id="_ajax_nonce-add-category" name="_ajax_nonce-add-category" value="c7402d10a1">					<span id="category-ajax-response"></span>
				</p>
			</div>
			</div>

There's no change to the tab markup here. Can you please help clarify how to test it?

@joedolson commented on PR #11035:


11 days ago
#9

@amberhinds Weird. I just did exactly the same thing, and I can see the updated source. I don't know why you'd have been seeing anything different. Playground wouldn't have any cache, so it can't be that.

Maybe just try again? Perhaps Playground failed to apply the patch? I'll also update the branch, in case that could have caused any issues.

@alh0319 commented on PR #11035:


11 days ago
#10

Fun fact: if you're using Brave browser and have shields up for Playground, it doesn't apply patches. Also, the installed plugins list is different.

I see it and testing now. Will comment again shortly.

#11 @alh0319
11 days ago

I tested this PR with both NVDA in Chrome on Windows and VoiceOver in Chrome and Safari on Mac. It has the expected aria-attributes and keyboard interaction patterns.

In VoiceOver, the tab selection is not announced after it is made, though the aria-selected attribute is correctly added. This is announced in NVDA and I can't see anything wrong with it so I believe this may be a recent Mac-specific bug.

I think this patch meets accessibility requirements.

@alh0319 commented on PR #11035:


11 days ago
#12

This looks good to me. More detailed comment in Trac.

#13 @joedolson
11 days ago

  • Keywords commit added

Based on the functional testing, marking for commit.

#14 @joedolson
11 days ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 61764:

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.

Note: See TracTickets for help on using tickets.