Make WordPress Core

Opened 6 weeks ago

Closed 7 days ago

#66038 closed defect (bug) (fixed)

Theme install: Disabled buttons are only visually disabled and still focusable

Reported by: afercia Owned by: afercia
Priority: normal Milestone: 7.2
Component: Themes Version:
Severity: normal Keywords: has-patch axe-core
Cc: Focuses: accessibility

Description (last modified by afercia)

In ​the theme-install.php page, a few button elements look visually disabled by the means of a CSS class disabled applied to them.

However, there's no semantics to convey their disabled state. No disabled or aria-disabled attributes are present.

As a consequence, these buttons are still focusable even though the disabled CSS class resets any focus indication styling. When tabbing through the UI, there is an invisible tab stop.

An example of these buttons is the 'Activated' button in the card of the currently active theme. See attached screenshot.

There are more buttons with the same issue. Just search for the disabled class on all buttons in the theme-install.php file and observe they don't have any disabled semantics.

Discovered while testing the experimental PR for #66015 / ​https://github.com/WordPress/wordpress-develop/pull/13348. Axe-core reports a color contrast violation for these buttons. It thinks they are regular buttons and flags the button text light gray color as a violation for insufficient color contrast ratio.

All these buttons should get a disabled attribute.

Focus style uses the same color of the background color.

One more problem occurs for the 'Customize' button of the active theme.

The focus style uses the same color of the background. As such, the focus style is not visible. Generally, using the same color for background and focus style doesn't seem to be a great idea.

Even when changing the admin color scheme (under the Profile settings), any color scheme applies the same color for the focus style and the background of the H3 at the bottom of the active theme card. This needs to be changed so that the focus style is visible.

Attachments (7)

01 only visually disabled.png​ (191.8 KB ) - added by afercia 6 weeks ago.
ticket-66038-before.png​ (82.3 KB ) - added by arkaprabhachowdhury 5 weeks ago.
Before patch: active theme action appears visually disabled but remains focusable.
ticket-66038-after-focus.png​ (319.7 KB ) - added by arkaprabhachowdhury 5 weeks ago.
After patch: disabled active-theme control is skipped and keyboard focus is visible on the next enabled action.
ticket-66038-before.2.png​ (82.3 KB ) - added by arkaprabhachowdhury 5 weeks ago.
Before patch screenshot
ticket-66038-after-focus.2.png​ (319.7 KB ) - added by arkaprabhachowdhury 5 weeks ago.
After patch screenshot: disabled active-theme control is skipped and keyboard focus is visible on the next enabled action.
ticket-66038-before-real.png​ (191.8 KB ) - added by arkaprabhachowdhury 5 weeks ago.
Before patch: original ticket screenshot showing the visually disabled but focusable control.
Theme accessibility.png​ (52.2 KB ) - added by sanayasir 4 weeks ago.

Download all attachments as: .zip

Change History (27)

#1 @afercia
6 weeks ago

  • Description modified (diff)

This ticket was mentioned in ​PR #13390 on ​WordPress/wordpress-develop by ​@sainathpoojary.


6 weeks ago
#2

  • Keywords has-patch added

This PR fixes two accessibility issues in the Theme Installer related to disabled buttons and focus visibility:

  1. Disabled semantics: Replaces the visual-only .disabled CSS class with proper semantic attributes (disabled for <button> elements, and aria-disabled="true" tabindex="-1" for <a> elements). This removes them from the tab order.
  2. Invisible focus ring: Updates the focus ring color to #fff for secondary buttons on the active theme card. Previously, the default focus ring color blended exactly with the theme name background, making it invisible when reached via keyboard.

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

## Use of AI Tools

AI assistance: Yes
Tool(s): Github Copilot
Model(s): Claude Sonnet 4.6
Used for: Edge-case checks, and assistance with the PR description; implementation and testing were reviewed and verified by me.

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


5 weeks ago

#4 @afercia
5 weeks ago

  • Keywords axe-core added

#5 @arkaprabhachowdhury
5 weeks ago

Test Report

Description

This report validates that PR #13390 addresses Trac #66038.

Patch tested: ​PR #13390 at ebeb0f07e31bbcc72f79a28eaac9d875e387f04e.

The issue concerns Theme Installer controls that are visually disabled but remain focusable, and focus visibility for active-theme action buttons.

Environment

  • WordPress: 7.2-alpha-20260904.123850
  • Browser: Chrome
  • OS: Windows
  • Theme: Twenty Twenty-Five
  • Server: WordPress Playground

Steps to Test

  1. Open the ​PR-specific WordPress Playground.
  2. Open /wp-admin/theme-install.php?browse=popular.
  3. Inspect the active theme card and compare its controls with other theme cards.
  4. Navigate through the controls with Tab and Shift+Tab.

Expected Results

  • The active theme action is a native disabled button and is not available for activation.
  • The disabled control is skipped in keyboard navigation.
  • Other themes retain enabled Install, Activate, and Preview actions.
  • Focus styling is visible and consistent with Core styling.

Actual Results

  • [pass] The PR-specific Playground and Theme Installer loaded successfully.
  • [pass] Twenty Twenty-Five displayed Activated as a native disabled button.
  • [pass] Other theme cards displayed enabled Install, Activate, and Preview actions.
  • [pass] Shift+Tab from Customize moved to the preceding search field rather than the disabled Activated button.
  • [pass] Tab from Customize moved to the next enabled Install action, which matched the focus-visible state.
Last edited 5 weeks ago by arkaprabhachowdhury (previous) (diff)

@arkaprabhachowdhury
5 weeks ago

Before patch: active theme action appears visually disabled but remains focusable.

@arkaprabhachowdhury
5 weeks ago

After patch: disabled active-theme control is skipped and keyboard focus is visible on the next enabled action.

@arkaprabhachowdhury
5 weeks ago

Before patch screenshot

@arkaprabhachowdhury
5 weeks ago

After patch screenshot: disabled active-theme control is skipped and keyboard focus is visible on the next enabled action.

@arkaprabhachowdhury
5 weeks ago

Before patch: original ticket screenshot showing the visually disabled but focusable control.

#6 @arkaprabhachowdhury
5 weeks ago

Additional screenshots for the test report:

#7 @sanayasir
4 weeks ago

Tested the changes on the Theme Install screen.

  • The buttons that use the disabled CSS class now have the disabled attribute, so they are no longer focusable via keyboard navigation.
  • The previously invisible tab stops are no longer present.
  • The active theme's "Customize" button now has a visible focus style.
  • The focus indication remains visible when switching between the available admin color schemes.
  • No regressions were observed in the Theme Install screen.

The changes work as expected from my testing.

#8 @kthibault
3 weeks ago

Tested PR #13390 in WordPress Playground on:

  • macOS Tahoe 26.5
  • Chrome 153.0.8010.53 (Official Build, arm64)

Confirmed:

  • On the active Twenty Twenty-Five theme card, the disabled “Activated” control is skipped during keyboard navigation.
  • The “Customize” control has a visible focus indicator in the PR version.
  • Shift+Tab moves back correctly without landing on the disabled “Activated” control.

The fix worked as expected in this environment.

AI assistance: ChatGPT was used for guidance on the testing process and help drafting this report. All testing and observations were performed and verified manually.

#9 @afercia
3 weeks ago

  • Owner set to afercia
  • Status new → assigned

​@sainathpoojary commented on ​PR #13390:


3 weeks ago
#10

Done @joedolson. Switched all button elements to aria-disabled="true" instead of the native disabled attribute, and removed tabindex="-1" from the anchor elements so everything stays in the tab order.

One thing came up on the CSS side. The global .disabled class in buttons.css suppresses box-shadow with !important, which means these buttons now receive focus but have no visible focus ring. To fix this, I added rules in themes.css using !important to override the global styling and force the focus rings to show.

Does this approach make sense or is there any other way we can handle the focus ring here?

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


2 weeks ago

​@joedolson commented on ​PR #13390:


2 weeks ago
#12

@SainathPoojary Another option would be to remove the .disabled class and attach the styles to [aria-disabled="true"], but that could introduce other complications. That's what's going on for the metabox mover buttons in the dashboard (common.css, .postbox .handle-order-higher[aria-disabled="true"], .postbox .handle-order-lower[aria-disabled="true"])

Overall, avoiding introducing !important is preferable, if possible. But if removing the class requires a ton of other changes, it may not be worth it.

If you change the class, make sure that all functionality is still properly nooped.

​@joedolson commented on ​PR #13390:


2 weeks ago
#13

@afercia and I discussed this, and agreed that our preferred pattern is to use aria-disabled and leave the control focusable with disabled styles, like we currently use on the dashboard.

​@afercia commented on ​PR #13390:


9 days ago
#14

I rebased on top of latest trunk.
Will post a comment on the Trac ticket as there is a decision that should be made.

#15 @afercia
9 days ago

I tested latest ​PR 13390. Buttons and links now use aria-disabled, thanks for updating that.

There is a decision that should be made though. Some of these 'buttons' are actually links styled as buttons.

When they are enabled, they do have a href attribute with a URL for the activation or to the preview in the customier.

When they are disabled, they are still links. They don't have a href attribute though. As such they are not focusable. Examples:

<a class="button button-primary button-compact disabled" aria-label="Cannot Activate Twenty Twenty-Five" aria-disabled="true">Cannot Activate</a>

or

<a class="button button-compact disabled" aria-disabled="true">Live Preview</a>

If we want these links to be still focusable and discoverable, we have a few options. Personally, I'd like avoiding playing with a so called 'incomplete URL fragment identifier' such as href="#" or playing with tabindex.

If there is no specific reason why these controls must still be links when disabled, I'd rather render them as a button element: <button type="button" ... aria-disabled="true"> ...

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


8 days ago

#17 follow-up: @joedolson
8 days ago

I support switching these to buttons; it's a much more appropriate control for this.

#18 in reply to: ↑ 17 @afercia
7 days ago

Replying to joedolson:

I support switching these to buttons; it's a much more appropriate control for this.

For context, this is already the case ​for some of these controls where the control is a link with an href attribute when enabled and a button when disabled.

​@afercia commented on ​PR #13390:


7 days ago
#19

I pushed a commit to use aria-disabled buttons rather than links.

I'm _not_ addressing the focus style for aria-disabeld buttons and I think it should be addressed in a separate ticket / PR as it is a broader change that impacts all the atyles from buttons.css, colors, with a few !important annotations.

#20 @afercia
7 days ago

  • Resolution → fixed
  • Status assigned → closed

In 64243:

Themes: Improve semantics and accessibility of the Theme installer disabled controls.

Most of the disabled controls in the Theme installer were rendered as <a> elements without a href attribute. Just a few of them were rendered as buttons when disabled. This change improves semantics, interaction, and accessibility by making all these controls buttons that are still focusable and that use aria-disabled instead of a disabled attribute.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/13390

Props sainathpoojary, arkaprabhachowdhury, sanayasir, kthibault, nicoblandel, joedolson, afercia.
Fixes #66038.

Note: See TracTickets for help on using tickets.