AppLayout.vue 1.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <script setup>
  2. import { ref, computed } from 'vue'
  3. import AppTopBar from '@/components/AppTopBar.vue'
  4. import AppMenu from '@/components/AppMenu.vue'
  5. import AppFooter from '@/components/AppFooter.vue'
  6. import AppMessage from '@/components/AppMessage.vue'
  7. import menu from '@/utils/menu'
  8. const mobileMenuActive = ref(false)
  9. const staticMenuInactive = ref(false)
  10. const menuClick = ref(false)
  11. const containerClass = computed(() => {
  12. return [
  13. 'layout-wrapper',
  14. 'layout-static',
  15. {
  16. 'layout-static-sidebar-inactive': staticMenuInactive.value,
  17. 'layout-mobile-sidebar-active': mobileMenuActive.value,
  18. },
  19. ]
  20. })
  21. const isDesktop = () => window.innerWidth >= 992
  22. const onMenuToggle = () => {
  23. menuClick.value = true
  24. if (isDesktop()) {
  25. staticMenuInactive.value = !staticMenuInactive.value
  26. } else {
  27. mobileMenuActive.value = !mobileMenuActive.value
  28. }
  29. }
  30. const onWrapperClick = () => {
  31. if (!menuClick.value) {
  32. mobileMenuActive.value = false
  33. }
  34. menuClick.value = false
  35. }
  36. </script>
  37. <template>
  38. <div :class="containerClass" @click="onWrapperClick">
  39. <AppTopBar @menu-toggle="onMenuToggle" />
  40. <div class="layout-sidebar">
  41. <AppMenu :model="menu" />
  42. </div>
  43. <div class="layout-main-container">
  44. <div class="layout-main">
  45. <AppMessage />
  46. <slot />
  47. </div>
  48. <AppFooter />
  49. </div>
  50. <Transition name="layout-mask">
  51. <div class="layout-mask p-component-overlay" v-if="mobileMenuActive"></div>
  52. </Transition>
  53. </div>
  54. </template>