nhsuk-frontend icon indicating copy to clipboard operation
nhsuk-frontend copied to clipboard

Skiplink target

Open lee-richardson-infinityworks opened this issue 4 years ago • 5 comments

Hi, I'm working on something using the NHS React Components (https://github.com/NHSDigital/nhsuk-react-components) which is based on this repo's work.

Their skip link implementation includes the fix for the iOS VoiceOver bug. I have found that screen readers (NVDA and Chrome's. I don't have iOS access) will quite randomly decide whether or not to read just the header or the content under the header as well. If I changed it to focus on the element of the href prop it always reads the content.

Could someone give me some more details on how the bug fix works? Is it necessary to use the h1 or would it also work to manually focus on main content element? Essentially can we get the functionality of a normal skip link to the main content, without invoking the bug?

Thanks.

Hey @lee-richardson-infinityworks thanks for opening this issue.

This is the first we've heard of this issue with the Skip link. Just so I'm following this correctly, is this issue something that has been fixed within the React port of this library, but not in the core NHS.UK frontend?

Adam

chrimesdev avatar Mar 22 '21 15:03 chrimesdev

My screen reader issue exists in the React port due to the VoiceOver fix, so it should be here in the NHSUK frontend as well since it's the same functionality. I would like to fix my screen reader issue without reintroducing the VoiceOver bug. I don't have access to an iOS device right now to test, and the people on the React port repo won't know anything about the bug since the functionality was copied from here. I'm not an accessibility expert though so I could do with having the whole thing clarified first. Like what are your requirements for the skip link? If it should be reading the content, and did so for your tests, then it could be something in my project or a change in the screen readers. If it doesn't need to read the content then we don't really have a problem, just an variation.

For reference, the React implementation can be found here. There isn't much difference between the two implementations, but I can imagine the being fixed in the focusElement method:

  private focusElement = (element: HTMLElement): void => {
    // Sometimes custom focus code can cause a loop of focus events
    // (especially in IE11), so check for attributes before performing
    // focus actions and DOM manipulation.
    if (!element.hasAttribute('tabIndex')) {
      element.setAttribute('tabIndex', '-1');
    }
    if (document.activeElement !== element) {
      element.focus();
    }
  };

A lot of the extra little bits are there to make it work more nicely with React (i.e. allowing custom onClick handlers, allowing the default behaviour to be disabled, and allowing a ref to be passed directly to the SkipLink), as well as a few guards to make sure that attributes aren't being added to elements that don't exist.

Tomdango avatar Mar 22 '21 15:03 Tomdango

Hey @lee-richardson-infinityworks thanks for the clarification on that. The skip link jumps you to the <main> element content (using an anchor and id of #maincontent by default) and if using a screen reader the screen reader should start reading out the content from the beginning of that element (usually a <h1>) rather than everything above it.

Skip link example on the NHS digital service manual

As you said this could be a problem within your application or it could be a problem in the React port or here in NHS.UK frontend itself. However it its quite difficult to replicate and fix the problem without further information. Especially since this sounds like it "will quite randomly decide whether or not to read just the header or the content under the header as well."

Do you have any code or examples you can share with us?

chrimesdev avatar Mar 22 '21 16:03 chrimesdev

That example doesn't have the JS in use, but if you look at the skip link belonging to the page itself which that example is on, it does have the JS so the click event focuses on the h1. Presumably that happens immediately after the #maincontent navigation, and so steam rollers it. If there is no h1 it remains on the #maincontent. You can also check by disabling JS in dev tools and clicking the same link. It goes to #maincontent.

https://github.com/nhsuk/nhsuk-frontend/blob/master/packages/components/skip-link/skip-link.js