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/components/Global/PageContainer.vue | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

(limited to 'src/components/Global/PageContainer.vue')

diff --git a/src/components/Global/PageContainer.vue b/src/components/Global/PageContainer.vue
index e766d38d..c979759b 100644
--- a/src/components/Global/PageContainer.vue
+++ b/src/components/Global/PageContainer.vue
@@ -5,11 +5,17 @@
 </template>
 
 <script>
+import SetFocusMixin from '@/components/Mixins/SetFocusMixin';
 export default {
   name: 'PageContainer',
+  mixins: [SetFocusMixin],
+  created() {
+    this.$root.$on('skip-navigation', () => {
+      this.setFocus(this.$el);
+    });
+  },
 };
 </script>
-
 <style lang="scss" scoped>
 main {
   width: 100%;
@@ -18,6 +24,12 @@ main {
   padding-bottom: $spacer * 3;
   padding-left: $spacer;
   padding-right: $spacer;
+
+  &:focus-visible {
+    box-shadow: inset 0 0 0 2px theme-color('primary');
+    outline: none;
+  }
+
   @include media-breakpoint-up($responsive-layout-bp) {
     padding-left: $spacer * 2;
   }
-- 
cgit v1.2.3

