<template> <div class="container" :class="theme" > <transition name="slide"> <Sidebar v-if="showSidebar" @toggle="(state) => showSidebar = state" /> </transition> <Header :toggle-sidebar="toggleSidebar" /> <div class="content"> <!-- key forces rerender when new and old path use same component --> <router-view /> </div> </div> </template> <script> import { mapState } from 'vuex'; import EventBus from '../../js/event-bus'; import Header from '../header/header.vue'; import Sidebar from '../sidebar/sidebar.vue'; function theme(state) { return state.ui.theme; } function toggleSidebar(state) { this.showSidebar = typeof state === 'boolean' ? state : !this.showSidebar; } function mounted() { document.addEventListener('click', () => { EventBus.$emit('blur'); }); } export default { components: { Header, Sidebar, }, data() { return { showSidebar: false, }; }, computed: { ...mapState({ theme, }), }, mounted, methods: { toggleSidebar, }, }; </script> <style lang="scss"> @import 'theme'; .container { position: relative; height: 100%; display: flex; flex-direction: column; overflow: hidden; background: var(--background-soft); color: var(--text); } .content { display: flex; flex-direction: column; flex-grow: 1; overflow-y: auto; overflow-x: hidden; } .content-inner { flex-grow: 1; overflow-y: auto; overflow-x: hidden; box-shadow: 0 0 3px var(--shadow-weak); z-index: 1; } .slide-enter-active, .slide-leave-active { &.sidebar-container { transition: background .2s ease-in-out; } .sidebar { transition: transform .2s ease-in-out; } } .slide-enter, .slide-leave-to { &.sidebar-container { background: transparent; } .sidebar { transform: translate(-100%, 0); } } .column { width: 1200px; max-width: 100%; padding: 0 1rem; margin: 0 auto; box-sizing: border-box; } </style>