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 <!-- Scroll to top button --> 8 <button-back-to-top /> 9 </page-container> 10 </div> 11</template> 12 13<script> 14import AppHeader from '@/components/AppHeader'; 15import AppNavigation from '@/components/AppNavigation'; 16import PageContainer from '@/components/Global/PageContainer'; 17import ButtonBackToTop from '@/components/Global/ButtonBackToTop'; 18import JumpLinkMixin from '@/components/Mixins/JumpLinkMixin'; 19 20export default { 21 name: 'App', 22 components: { 23 AppHeader, 24 AppNavigation, 25 PageContainer, 26 ButtonBackToTop, 27 }, 28 mixins: [JumpLinkMixin], 29 data() { 30 return { 31 routerKey: 0, 32 }; 33 }, 34 watch: { 35 $route: function () { 36 this.$nextTick(function () { 37 this.setFocus(this.$refs.focusTarget.$el); 38 }); 39 }, 40 }, 41 mounted() { 42 this.$root.$on('refresh-application', () => this.refresh()); 43 }, 44 methods: { 45 refresh() { 46 // Changing the component :key value will trigger 47 // a component re-rendering and 'refresh' the view 48 this.routerKey += 1; 49 }, 50 }, 51}; 52</script> 53 54<style lang="scss" scoped> 55.app-container { 56 display: grid; 57 grid-template-columns: 100%; 58 grid-template-rows: auto; 59 grid-template-areas: 60 'header' 61 'content'; 62 63 @include media-breakpoint-up($responsive-layout-bp) { 64 grid-template-columns: $navigation-width 1fr; 65 grid-template-areas: 66 'header header' 67 'navigation content'; 68 } 69} 70 71.app-header { 72 grid-area: header; 73 position: sticky; 74 top: 0; 75 z-index: $zindex-fixed + 1; 76} 77 78.app-navigation { 79 grid-area: navigation; 80} 81 82.app-content { 83 grid-area: content; 84 background-color: $white; 85} 86</style> 87