From 045bc4e5eea3f66ded3a4eb9ed6cb989cff4360a Mon Sep 17 00:00:00 2001 From: Vben Date: Sat, 3 May 2025 18:05:26 +0800 Subject: [PATCH] feat: support smooth auto-scroll to active menu item (#6102) --- .../ui-kit/menu-ui/src/components/menu.vue | 30 +++++++-- .../menu-ui/src/hooks/use-menu-scroll.ts | 46 +++++++++++++ packages/@core/ui-kit/menu-ui/src/menu.vue | 6 -- packages/@core/ui-kit/menu-ui/src/types.ts | 6 ++ packages/effects/access/src/accessible.ts | 2 +- .../effects/layouts/src/basic/menu/menu.vue | 1 + .../layouts/src/basic/menu/use-navigation.ts | 64 ++++++++++++------- .../helpers/__tests__/generate-menus.test.ts | 15 ++--- packages/utils/src/helpers/generate-menus.ts | 55 +++++++++------- 9 files changed, 155 insertions(+), 70 deletions(-) create mode 100644 packages/@core/ui-kit/menu-ui/src/hooks/use-menu-scroll.ts diff --git a/packages/@core/ui-kit/menu-ui/src/components/menu.vue b/packages/@core/ui-kit/menu-ui/src/components/menu.vue index db4bda31..88760456 100644 --- a/packages/@core/ui-kit/menu-ui/src/components/menu.vue +++ b/packages/@core/ui-kit/menu-ui/src/components/menu.vue @@ -31,6 +31,7 @@ import { createSubMenuContext, useMenuStyle, } from '../hooks'; +import { useMenuScroll } from '../hooks/use-menu-scroll'; import { flattedChildren } from '../utils'; import SubMenu from './sub-menu.vue'; @@ -44,6 +45,7 @@ const props = withDefaults(defineProps(), { mode: 'vertical', rounded: true, theme: 'dark', + scrollToActive: false, }); const emit = defineEmits<{ @@ -206,15 +208,19 @@ function handleResize() { isFirstTimeRender = false; } -function getActivePaths() { - const activeItem = activePath.value && items.value[activePath.value]; +const enableScroll = computed( + () => props.scrollToActive && props.mode === 'vertical' && !props.collapse, +); - if (!activeItem || props.mode === 'horizontal' || props.collapse) { - return []; - } +const { scrollToActiveItem } = useMenuScroll(activePath, { + enable: enableScroll, + delay: 320, +}); - return activeItem.parentPaths; -} +// 监听 activePath 变化,自动滚动到激活项 +watch(activePath, () => { + scrollToActiveItem(); +}); // 默认展开菜单 function initMenu() { @@ -318,6 +324,16 @@ function removeSubMenu(subMenu: MenuItemRegistered) { function removeMenuItem(item: MenuItemRegistered) { Reflect.deleteProperty(items.value, item.path); } + +function getActivePaths() { + const activeItem = activePath.value && items.value[activePath.value]; + + if (!activeItem || props.mode === 'horizontal' || props.collapse) { + return []; + } + + return activeItem.parentPaths; +}