Problem/Motivation

The Entity Display forms ("manage display" and "manage form display") have a visually-hidden button:

<input class="visually-hidden button js-form-submit form-submit" data-drupal-selector="edit-refresh" id="edit-refresh" name="op" value="Refresh" type="submit">

This button is triggered programatically as part of Field UI's ajax behaviours. It seems this button is NOT intended to be activated by human users, hence the visually-hidden class. Mouse/pointer users cannot operate this button, because it has zero height and width.

However, this button is still in the keyboard tabbing order, and can be activated by a keyboard user. The visually-hidden class means the focused button isn't perceivable though, which is a failure of WCAG 2.4.7 Focus Visible. It acts as a confusing extra tab-stop for keyboard users, who can activate it by accident (though doing so seems to be harmless).

Proposed resolution

Hide the button from all users, not just sighted mouse/pointer users.

Possible Approaches:
The most reliable way to hide the button from all user is with display: none. This will hide it from screen readers, and remove it from the tabbing order for sighted keyboard-only users. There are a few ways we could do that.

  • Hide the refresh button with the .hidden class instead of .visually-hidden. REJECTED in #2, it was being overridden by author styles.
  • Hide the refresh button with the .hidden class instead of .visually-hidden, and provide a more specific override (like toolbar and contextual modules do, see comment #8).
  • Use a custom class for this button, and use display:none on that. WORKS see comment #2.
  • Use the HTML5 hidden attribute instead of the .visually-hidden class. See comment #8.

Important: will the button still accept a programatically-triggered mousedown event?

  • YES, still works in Firefox.
  • TODO: confirm this still works in other browsers.

Remaining tasks

  • Patch to hide the button
  • Make sure the need to hide it from all users is documented in comments.
  • Cross-browser testing - test the tabbing order in all our supported browsers, confirm the button isn't tabbable.
  • Cross-browser manual testing - Confirm the trigger('mousedown') in Drupal.fieldUIOverview.AJAXRefreshRows() still works, in all our supported browsers.

User interface changes

Accessibility improvements - remove the confusing button from the keyboard-only and screen reader experience.
No visual design changes.

API changes

None.

Data model changes

None.

Issue fork drupal-2990588

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

andrewmacpherson created an issue. See original summary.

andrewmacpherson’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +JavaScript, +stable
StatusFileSize
new1.78 KB

This patch replaces the .visually-hidden class with a custom class, which gets CSS display:none.

First I tried using Drupal core's existing .hidden class, but it wasn't specific enough and was overridden by button styles. Feel free to suggest a better class or selector.

The patch here adds the new style rule to the Stable theme. I hope that's OK - we've allowed accessibility bug fixes in Stable theme before now.

Will this need cross-browser testing? So far I've only tested this in Firefox 61 (Linux). It seems a mousedown event can still be programatically triggered on a button with display:none, which is good. I used a few console.log lines in field_ui.js and ajax.js to check this.

andrewmacpherson’s picture

StatusFileSize
new1.85 KB
new1.56 KB

The previous patch only worked on "manage form display", not "manage display", so I've updated the selectors and button class.

Manually tested in Firefox 61 (Linux) and Chrome 68 (Linux), with Seven and Stark themes.

andrewmacpherson’s picture

Issue tags: -Accessibility +accessibility

Will this need cross-browser testing?

andrewmacpherson’s picture

Issue tags: +CSS
shaal’s picture

Status: Needs review » Reviewed & tested by the community

I tested on Ubuntu 18.10, with the following setup

  • Google Chrome 72.0.3626.119
  • Chromium 72.0.3626.96
  • Firefox Nightly 67.0a1
  • Windows 7+ IE11

After applying the patch, testing /admin/structure/types/manage/article/form-display and /admin/structure/types/manage/article/display.

Tabbing through the elements on the page, it does skip the visually-hidden button just before the save button.

oriol_e9g’s picture

Why not add !important in hidden helper class .hidden { display: none !important; } like bootstrap? We are adding other importants in similar classes, and it's fine to force hidden if you use hidden class.

oriol_e9g’s picture

Please, feel free to commit patch #3 if considerer that it's better create a new class instead to add an !important in a current class, #3 still RTBC.

oriol_e9g’s picture

StatusFileSize
new656 bytes
oriol_e9g’s picture

StatusFileSize
new1.02 KB
andrewmacpherson’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work

Re. #6 - Thanks @shaal, I see you tested the tabbing order.

Did you test whether the FIeld UI Javascript behaviours still work?

The part we need to know about is whether the hidden refresh button still works. Does triggering a mousedown programatically still work for a button with dispay: none? I think that warrants cross-browser testing too.

See my comment in #2 about this. The mousedown is triggered in Drupal.fieldUIOverview.AJAXRefreshRows(). It's a while since I had my head in this issue, and I find our AJAX system hard to grok. I'm not really clear what the refresh button if for. I can't recall where I put the console.log lines I mentioned. Manual testing involves changing formatter, formatter settings, etc.

Re. #7-10
That's certainly a good suggestion to consider, but I'd be very cautious about changing the implementation of .hidden in a minor release. It would potentially break things far beyond the refresh button in this issue, including existing sites. I'd defer to the framework managers about that. Can we file a follow-up issue about it making .hidden more robust generally, and keep this issue scoped to this button.

Also, my own ideas further to. #2

First I tried using Drupal core's existing .hidden class, but it wasn't specific enough and was overridden by button styles. Feel free to suggest a better class or selector.

I also noticed that other modules (contextual, toolbar, off-canvas) have run into the problem of .hidden being overridden. They all solve it like this, with a more specific selector for the .hidden class like this:

.toolbar .toolbar-bar .toolbar-tab.hidden {
  display: none;
}

So perhaps we should follow that pattern instead of the custom class I used in #2. It has the advantage of being easy to understand in the HTML without looking up the styles.

I don't recall if I tried using the HTML5 hidden attribute. That would allow us to avoid a custom class to the stylesheets. However the hidden attribute is typically implemented as display:none in user-agent styles, so they might also get overridden by author style. Adding that as something to try.

Updating the issue summary. Confirming the JS behaviour still works is the most important thing for review.

tim.plunkett’s picture

Issue tags: -accessibility (duplicate tag) +Accessibility

Fixing tag

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mgifford’s picture

Issue tags: -JavaScript +JavaScript, +wcag247

Tagging

Utkarsh_33 made their first commit to this issue’s fork.

utkarsh_33’s picture

Status: Needs work » Needs review

I have added a custom class to take of all the things described in the remaining tasks.I was able to hit the breakpoint for

Cross-browser manual testing - Confirm the trigger('mousedown') in Drupal.fieldUIOverview.AJAXRefreshRows() still works, in all our supported browsers.

atleast in Chrome.
The failing test seems to be random failures as they are failing on 11.x as well(atleast on my local).Marking it as needs review just to get an initial round of review.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs issue summary update

Hiding patches for clarity.

On a standard profile install of 11.x
Can confirm on /admin/structure/types/manage/article/form-display that tabbing through the page that focus is lost between the last gear icon and the "Save" button.

Applied the MR and focus no longer appears to be lost.

Solution of using a custom class also appears to be least disruptive in my opinion especially since it can be added this way. Wonder if there is other places this is also fixing.

Looks great to me!

smustgrave’s picture

nod_’s picture

Status: Reviewed & tested by the community » Needs work

Reading the IS the problem is that keyboard focus is possible. tabindex="-1" would fix that, can someone confirm that it works? Adding a new class and a bunch of display:none in the CSS is not the way to go.

utkarsh_33’s picture

Status: Needs work » Needs review

#28 seems to be a better approach, so I have reverted the class changes and added tabIndex to the button thus making it non tabbable.Also the mousedown trigger event is working so marking it as needs review again.Thanks!

nod_’s picture

need a small comment

Mithun S made their first commit to this issue’s fork.

mithun s’s picture

Added a rebase of the latest changes from the branch.
The MR looks mergable now. Thank you!

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Feedback appears to be addressed.

@Mithun S thanks for the rebase but only needed if the MR is unmergable just an FYI.

  • nod_ committed d0592e79 on 10.3.x
    Issue #2990588 by Utkarsh_33, andrewmacpherson, oriol_e9g, smustgrave,...

  • nod_ committed 6e1e0c29 on 10.4.x
    Issue #2990588 by Utkarsh_33, andrewmacpherson, oriol_e9g, smustgrave,...

  • nod_ committed 68a22a5c on 11.0.x
    Issue #2990588 by Utkarsh_33, andrewmacpherson, oriol_e9g, smustgrave,...

  • nod_ committed b97be27a on 11.x
    Issue #2990588 by Utkarsh_33, andrewmacpherson, oriol_e9g, smustgrave,...
nod_’s picture

Version: 11.x-dev » 10.3.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed b97be27a89 to 11.x and 68a22a5cc0 to 11.0.x and 6e1e0c29d0 to 10.4.x and d0592e79ef to 10.3.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.