1<template> 2 <div class="app-container"> 3 <app-header ref="focusTarget" class="app-header" @refresh="refresh" /> 4 <app-navigation class="app-navigation" /> 5 <page-container class="app-content"> 6 <router-view ref="routerView" :key="routerKey" /> 7 </page-container> 8 </div> 9</template> 10 11<script> 12import AppHeader from '@/components/AppHeader'; 13import AppNavigation from '@/components/AppNavigation'; 14import PageContainer from '../components/Global/PageContainer'; 15export default { 16 name: 'App', 17 components: { 18 AppHeader, 19 AppNavigation, 20 PageContainer 21 }, 22 data() { 23 return { 24 routerKey: 0 25 }; 26 }, 27 watch: { 28 $route: function() { 29 // $nextTick = DOM updated 30 this.$nextTick(function() { 31 // Get the focusTarget DOM element 32 let focusTarget = this.$refs.focusTarget.$el; 33 34 // Make focustarget programmatically focussable 35 focusTarget.setAttribute('tabindex', '-1'); 36 37 // Focus element 38 focusTarget.focus(); 39 40 // Remove tabindex from focustarget 41 // Reason: https://axesslab.com/skip-links/#update-3-a-comment-from-gov-uk 42 focusTarget.removeAttribute('tabindex'); 43 }); 44 } 45 }, 46 methods: { 47 refresh() { 48 // Changing the component :key value will trigger 49 // a component re-rendering and 'refresh' the view 50 this.routerKey += 1; 51 } 52 } 53}; 54</script> 55 56<style lang="scss" scoped> 57.app-container { 58 display: grid; 59 grid-template-columns: 100%; 60 grid-template-rows: auto; 61 grid-template-areas: 62 'header' 63 'content'; 64 65 @include media-breakpoint-up($responsive-layout-bp) { 66 grid-template-columns: $navigation-width 1fr; 67 grid-template-areas: 68 'header header' 69 'navigation content'; 70 } 71} 72 73.app-header { 74 grid-area: header; 75 position: sticky; 76 top: 0; 77 z-index: $zindex-fixed + 1; 78} 79 80.app-navigation { 81 grid-area: navigation; 82} 83 84.app-content { 85 grid-area: content; 86 background-color: $white; 87} 88</style> 89