main
vue 126 lines 3.21 KB
Raw
1 <template>
2 <div
3 id="app-main"
4 class="main"
5 :class="{ 'sidebar-collapsed': sidebarCollapsed, 'sidebar-opened': !sidebarCollapsed }"
6 >
7 <n-scrollbar
8 ref="scrollbar"
9 trigger="none"
10 :y-placement="isRTL ? 'left' : 'right'"
11 content-class="flex min-h-full flex-col"
12 :theme-overrides="{
13 railInsetVerticalRight: `${toolbarHeight}px 4px 4px auto`,
14 railInsetVerticalLeft: `${toolbarHeight}px auto 4px 4px`
15 }"
16 >
17 <Toolbar :boxed="toolbarBoxed" gradient="sidebar" />
18 <div
19 id="app-view"
20 class="view"
21 :class="{ boxed, 'view-padded': overridePadded === true, 'view-no-padded': overridePadded === false }"
22 >
23 <slot />
24 </div>
25 <MainFooter v-if="footerShown" :boxed />
26 </n-scrollbar>
27 </div>
28 </template>
29
30 <script lang="ts" setup>
31 import type { RouteLocationNormalizedGeneric } from "vue-router"
32 import { NScrollbar } from "naive-ui"
33 import { computed, onMounted, ref } from "vue"
34 import { useRoute, useRouter } from "vue-router"
35 import MainFooter from "@/app-layouts/common/MainFooter.vue"
36 import Toolbar from "@/app-layouts/common/Toolbar"
37 import { useThemeStore } from "@/stores/theme"
38
39 const themeStore = useThemeStore()
40 const router = useRouter()
41 const route = useRoute()
42 const sidebarCollapsed = computed<boolean>(() => themeStore.sidebar.collapsed)
43 const footerShown = computed(() => themeStore.isFooterShown)
44 const themeBoxed = computed<boolean>(() => themeStore.isBoxed)
45 const overrideBoxed = ref<boolean | undefined>(undefined)
46 const overridePadded = ref<boolean | undefined>(undefined)
47 const boxed = computed<boolean>(() => (overrideBoxed.value !== undefined ? overrideBoxed.value : themeBoxed.value))
48 const isRTL = computed<boolean>(() => themeStore.isRTL)
49 const toolbarBoxed = computed(() => themeStore.isToolbarBoxed)
50 const toolbarHeight = computed(() => themeStore.toolbarHeight)
51 const scrollbar = ref()
52
53 function checkThemeOverrides(currentRoute: RouteLocationNormalizedGeneric) {
54 if (currentRoute.meta?.theme?.boxed?.enabled !== undefined) {
55 overrideBoxed.value = currentRoute.meta.theme.boxed.enabled
56 } else {
57 overrideBoxed.value = undefined
58 }
59
60 if (currentRoute.meta?.theme?.padded?.enabled !== undefined) {
61 overridePadded.value = currentRoute.meta.theme.padded.enabled
62 } else {
63 overridePadded.value = undefined
64 }
65 }
66
67 router.beforeEach(checkThemeOverrides)
68
69 onMounted(() => {
70 checkThemeOverrides(route)
71
72 router.afterEach(() => {
73 if (scrollbar?.value?.scrollTo) {
74 scrollbar?.value.scrollTo({ top: 0, behavior: "smooth" })
75 }
76 })
77 })
78 </script>
79
80 <style lang="scss" scoped>
81 @import "./variables";
82
83 .main {
84 width: 100%;
85 overflow: hidden;
86 background-color: var(--bg-body-color);
87 transition: all var(--sidebar-anim-ease) var(--sidebar-anim-duration);
88
89 .view {
90 padding: 0 var(--view-padding);
91 flex-grow: 1;
92 width: 100%;
93 margin: 0 auto;
94
95 &.boxed {
96 max-width: var(--boxed-width);
97 }
98 &.view-no-padded {
99 padding: 0;
100 }
101 }
102
103 @media (max-width: $sidebar-bp) {
104 &.sidebar-opened {
105 /*
106 transform: scale(0.8) translateX(100%) rotateY(35deg);
107 transform-origin: center left;
108 border-radius: 16px;
109 */
110
111 overflow: hidden;
112 opacity: 0.5;
113 }
114 }
115
116 @media (min-width: ($sidebar-bp + 1px)) {
117 :deep() {
118 header.toolbar {
119 .logo-box {
120 display: none;
121 }
122 }
123 }
124 }
125 }
126 </style>