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@import 'src/assets/styles/helpers'; 58 59.app-container { 60 display: grid; 61 grid-template-columns: 100%; 62 grid-template-rows: auto; 63 grid-template-areas: 64 'header' 65 'content'; 66 67 @include media-breakpoint-up($responsive-layout-bp) { 68 grid-template-columns: $navigation-width 1fr; 69 grid-template-areas: 70 'header header' 71 'navigation content'; 72 } 73} 74 75.app-header { 76 grid-area: header; 77 position: sticky; 78 top: 0; 79 z-index: $zindex-fixed + 1; 80} 81 82.app-navigation { 83 grid-area: navigation; 84} 85 86.app-content { 87 grid-area: content; 88 background-color: $white; 89} 90</style> 91