From 8026797012a0cbdce357a5c47304134fec9eca73 Mon Sep 17 00:00:00 2001
From: Derick Montague <derick.montague@ibm.com>
Date: Tue, 16 Feb 2021 09:47:03 -0600
Subject: Fix skip link 404 error on refresh bug

Problem:
When a user uses the skip link anchor to skip the navigation, the
route was being changed to /#main-content. This route does not
exist. If a user were to manually refresh the page, it would
return a 404. This link is critical to meet accessibility
guidelines and is needed by users that navigate with a keyboard.

The challenge is that we need to mirror a full page refresh on all
route changes, so we set focus on the app-header element on each route
change. When we click the skip to navigation link, there should not be
a route change. All we need is to set focus on the <main> element so
that the user can tab to the first tabbable element in the main content
section.

Solution:
- Use a native <a> element with an attached click event handler
- Prevent the default action of adding the hash to the URL
- Create a global mixin to reuse for route changes and skip link
activation
- Emit an event that can be listened for to call the global mixin

Signed-off-by: Derick Montague <derick.montague@ibm.com>
Change-Id: I4c2301b02f608eeb376ed2d1bd809f3d5c1bf545
---
 src/layouts/AppLayout.vue | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

(limited to 'src/layouts/AppLayout.vue')

diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue
index c2023dfb..d5b4c3df 100644
--- a/src/layouts/AppLayout.vue
+++ b/src/layouts/AppLayout.vue
@@ -15,6 +15,7 @@ import AppHeader from '@/components/AppHeader';
 import AppNavigation from '@/components/AppNavigation';
 import PageContainer from '@/components/Global/PageContainer';
 import ButtonBackToTop from '@/components/Global/ButtonBackToTop';
+import SetFocusMixin from '@/components/Mixins/SetFocusMixin';
 
 export default {
   name: 'App',
@@ -24,6 +25,7 @@ export default {
     PageContainer,
     ButtonBackToTop,
   },
+  mixins: [SetFocusMixin],
   data() {
     return {
       routerKey: 0,
@@ -31,20 +33,8 @@ export default {
   },
   watch: {
     $route: function () {
-      // $nextTick = DOM updated
       this.$nextTick(function () {
-        // Get the focusTarget DOM element
-        let focusTarget = this.$refs.focusTarget.$el;
-
-        // Make focustarget programmatically focussable
-        focusTarget.setAttribute('tabindex', '-1');
-
-        // Focus element
-        focusTarget.focus();
-
-        // Remove tabindex from focustarget
-        // Reason: https://axesslab.com/skip-links/#update-3-a-comment-from-gov-uk
-        focusTarget.removeAttribute('tabindex');
+        this.setFocus(this.$refs.focusTarget.$el);
       });
     },
   },
-- 
cgit v1.2.3

