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