|
|
@@ -1,74 +1,153 @@
|
|
|
-//- app/shared/MultiLevelMenu/index.pug
|
|
|
-nav.relative
|
|
|
-
|
|
|
- .flex.space-x-2(class="absolute md:relative md:block flex-col md:flex-row")
|
|
|
- .menu-item.relative(
|
|
|
- v-for='item in menuItems'
|
|
|
- :key='item.id'
|
|
|
- @mouseenter='openSubmenu = item.id'
|
|
|
- @mouseleave='openSubmenu = null'
|
|
|
- @click='handleMobileClick(item)'
|
|
|
- )
|
|
|
- button.flex.items-center.px-4.py-2.text-sm.font-medium.text-white.rounded-md.transition-all.duration-200(
|
|
|
- :class='getMenuItemClasses(item)'
|
|
|
- :aria-expanded='openSubmenu === item.id'
|
|
|
- )
|
|
|
- a(:href="item.href") {{ item.title }}
|
|
|
- svg.w-4.h-4.ml-1(
|
|
|
- :class='{"transform rotate-180": openSubmenu === item.id, "hidden": !item.children}'
|
|
|
- fill='none' stroke='currentColor' viewBox='0 0 24 24'
|
|
|
- )
|
|
|
- path(stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7')
|
|
|
-
|
|
|
- //- Выпадающее меню
|
|
|
- transition(
|
|
|
- enter-active-class='transition-all duration-300 ease-out'
|
|
|
- enter-from-class='opacity-0 transform -translate-y-2'
|
|
|
- enter-to-class='opacity-100 transform translate-y-0'
|
|
|
- leave-active-class='transition-all duration-200 ease-in'
|
|
|
- leave-from-class='opacity-100 transform translate-y-0'
|
|
|
- leave-to-class='opacity-0 transform -translate-y-2'
|
|
|
- )
|
|
|
- .absolute.left-0.mt-2.w-56.rounded-lg.shadow-xl.bg-white.ring-1.ring-black.ring-opacity-5.z-50( class="dark:bg-gray-800"
|
|
|
- v-if='item.children && openSubmenu === item.id'
|
|
|
- @mouseenter='openSubmenu = item.id'
|
|
|
+nav(class="relative")
|
|
|
+ div(class="hidden md:flex space-x-2")
|
|
|
+ div(
|
|
|
+ v-for="item in menuItems"
|
|
|
+ :key="item.id"
|
|
|
+ class="menu-item relative"
|
|
|
+ @mouseenter="openSubmenu = item.id"
|
|
|
+ @mouseleave="openSubmenu = null"
|
|
|
)
|
|
|
- .py-2
|
|
|
- .submenu-item.relative(
|
|
|
- v-for='child in item.children'
|
|
|
- :key='child.id'
|
|
|
- @mouseenter='openSubsubmenu = child.id'
|
|
|
- @mouseleave='openSubsubmenu = null'
|
|
|
+ button(
|
|
|
+ class="flex items-center px-4 py-2 text-sm font-medium rounded-md transition-all duration-200"
|
|
|
+ :class="getMenuItemClasses(item)"
|
|
|
+ :aria-expanded="openSubmenu === item.id"
|
|
|
)
|
|
|
- .flex.items-center.justify-between.px-4.py-2.text-sm.text-gray-700.cursor-pointer.transition-colors.duration-200(
|
|
|
- :class='"dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700" + {"rounded-lg": !child.children}'
|
|
|
- )
|
|
|
- | {{ child.title }}
|
|
|
- svg.w-4.h-4(
|
|
|
- :class='{"transform rotate-90": openSubsubmenu === child.id, "hidden": !child.children}'
|
|
|
- fill='none' stroke='currentColor' viewBox='0 0 24 24'
|
|
|
+ span {{ item.title }}
|
|
|
+ svg(
|
|
|
+ v-if="item.children"
|
|
|
+ class="w-4 h-4 ml-1 transition-transform duration-200"
|
|
|
+ :class="{'transform rotate-180': openSubmenu === item.id}"
|
|
|
+ fill="none"
|
|
|
+ stroke="currentColor"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
)
|
|
|
- path(stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 5l7 7-7-7')
|
|
|
-
|
|
|
- //- Второй уровень
|
|
|
- transition(
|
|
|
- enter-active-class='transition-all duration-300 ease-out'
|
|
|
- enter-from-class='opacity-0 transform translate-x-2'
|
|
|
- enter-to-class='opacity-100 transform translate-x-0'
|
|
|
- )
|
|
|
- .absolute.left-full.top-0.ml-1.w-56.rounded-lg.shadow-xl.bg-white.ring-1.ring-black.ring-opacity-5.z-50( class="dark:bg-gray-800"
|
|
|
- v-if='child.children && openSubsubmenu === child.id'
|
|
|
- )
|
|
|
- .py-2
|
|
|
- .px-4.py-2.text-sm.text-gray-700.cursor-pointer.transition-colors.duration-200(class="dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
|
- v-for='subchild in child.children'
|
|
|
- :key='subchild.id'
|
|
|
- ) {{ subchild.title }}
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7")
|
|
|
+
|
|
|
+ div(
|
|
|
+ v-if="item.children && openSubmenu === item.id"
|
|
|
+ class="absolute left-0 mt-2 w-56 rounded-lg shadow-xl bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 z-50"
|
|
|
+ @mouseenter="openSubmenu = item.id"
|
|
|
+ )
|
|
|
+ div(class="py-2")
|
|
|
+ div(
|
|
|
+ v-for="child in item.children"
|
|
|
+ :key="child.id"
|
|
|
+ class="submenu-item relative"
|
|
|
+ @mouseenter="openSubsubmenu = child.id"
|
|
|
+ @mouseleave="openSubsubmenu = null"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ class="flex items-center justify-between px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors duration-200"
|
|
|
+ :class="{'rounded-lg': !child.children}"
|
|
|
+ @click="handleMenuClick(child)"
|
|
|
+ )
|
|
|
+ span {{ child.title }}
|
|
|
+ svg(
|
|
|
+ v-if="child.children"
|
|
|
+ class="w-4 h-4 transition-transform duration-200"
|
|
|
+ :class="{'transform rotate-90': openSubsubmenu === child.id}"
|
|
|
+ fill="none"
|
|
|
+ stroke="currentColor"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ )
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7")
|
|
|
+
|
|
|
+ div(
|
|
|
+ v-if="child.children && openSubsubmenu === child.id"
|
|
|
+ class="absolute left-full top-0 ml-1 w-56 rounded-lg shadow-xl bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 z-50"
|
|
|
+ )
|
|
|
+ div(class="py-2")
|
|
|
+ div(
|
|
|
+ v-for="subchild in child.children"
|
|
|
+ :key="subchild.id"
|
|
|
+ class="px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors duration-200"
|
|
|
+ @click="handleMenuClick(subchild)"
|
|
|
+ ) {{ subchild.title }}
|
|
|
|
|
|
+ button(
|
|
|
+ class="md:hidden p-2 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
|
|
|
+ @click="toggleMobileMenu"
|
|
|
+ aria-label="Открыть меню"
|
|
|
+ )
|
|
|
+ svg(class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24")
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16")
|
|
|
|
|
|
-
|
|
|
- //- Mobile menu button (скрытый на десктопе)
|
|
|
- button.mobile-menu-button(@click="isMobileMenuOpen=!isMobileMenuOpen" class='md:hidden p-2 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700')
|
|
|
- svg.w-6.h-6(fill='none' stroke='currentColor' viewBox='0 0 24 24')
|
|
|
- path(stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 6h16M4 12h16M4 18h16')
|
|
|
-
|
|
|
+ div(
|
|
|
+ v-if="isMobileMenuOpen"
|
|
|
+ class="fixed inset-0 z-50 md:hidden"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ class="fixed inset-0 bg-black bg-opacity-50"
|
|
|
+ @click="closeMobileMenu"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ class="fixed inset-y-0 left-0 w-64 bg-white dark:bg-gray-800 shadow-xl transform transition-transform duration-300 ease-in-out"
|
|
|
+ :class="{'translate-x-0': isMobileMenuOpen, '-translate-x-full': !isMobileMenuOpen}"
|
|
|
+ )
|
|
|
+ div(class="flex flex-col h-full")
|
|
|
+ div(class="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700")
|
|
|
+ h2(class="text-lg font-semibold text-gray-800 dark:text-white") Меню
|
|
|
+ button(
|
|
|
+ @click="closeMobileMenu"
|
|
|
+ class="p-2 rounded-md text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
|
|
|
+ aria-label="Закрыть меню"
|
|
|
+ )
|
|
|
+ svg(class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24")
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12")
|
|
|
+
|
|
|
+ div(class="flex-1 overflow-y-auto")
|
|
|
+ div(class="py-2")
|
|
|
+ div(
|
|
|
+ v-for="item in menuItems"
|
|
|
+ :key="item.id"
|
|
|
+ class="mobile-menu-item"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ class="flex items-center justify-between px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors"
|
|
|
+ @click="toggleMobileSubmenu(item)"
|
|
|
+ )
|
|
|
+ span(class="font-medium") {{ item.title }}
|
|
|
+ svg(
|
|
|
+ v-if="item.children"
|
|
|
+ class="w-4 h-4 transition-transform duration-200"
|
|
|
+ :class="{'transform rotate-180': openMobileSubmenu === item.id}"
|
|
|
+ fill="none"
|
|
|
+ stroke="currentColor"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ )
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7")
|
|
|
+
|
|
|
+ div(
|
|
|
+ v-if="item.children && openMobileSubmenu === item.id"
|
|
|
+ class="bg-gray-50 dark:bg-gray-900"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ v-for="child in item.children"
|
|
|
+ :key="child.id"
|
|
|
+ class="mobile-submenu-item"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ class="flex items-center justify-between px-6 py-3 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors"
|
|
|
+ @click="toggleMobileSubsubmenu(child)"
|
|
|
+ )
|
|
|
+ span {{ child.title }}
|
|
|
+ svg(
|
|
|
+ v-if="child.children"
|
|
|
+ class="w-4 h-4 transition-transform duration-200"
|
|
|
+ :class="{'transform rotate-90': openMobileSubsubmenu === child.id}"
|
|
|
+ fill="none"
|
|
|
+ stroke="currentColor"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ )
|
|
|
+ path(stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7")
|
|
|
+
|
|
|
+ div(
|
|
|
+ v-if="child.children && openMobileSubsubmenu === child.id"
|
|
|
+ class="bg-gray-100 dark:bg-gray-800"
|
|
|
+ )
|
|
|
+ div(
|
|
|
+ v-for="subchild in child.children"
|
|
|
+ :key="subchild.id"
|
|
|
+ class="px-8 py-2 text-gray-500 dark:text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-600 cursor-pointer transition-colors"
|
|
|
+ @click="handleMobileMenuClick(subchild)"
|
|
|
+ ) {{ subchild.title }}
|