1
0
Эх сурвалжийг харах

feat: tabbar support mouse wheel vertical (#5129)

* feat: tabbar support mouse wheel

* docs: add tabbar wheelable tips

* chore: resolve vitest test
Netfan 3 сар өмнө
parent
commit
7fbf7b189a

+ 1 - 0
packages/@core/preferences/__tests__/__snapshots__/config.test.ts.snap

@@ -83,6 +83,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
     "showMaximize": true,
     "showMore": true,
     "styleType": "chrome",
+    "wheelable": true,
   },
   "theme": {
     "builtinType": "default",

+ 1 - 0
packages/@core/preferences/src/config.ts

@@ -83,6 +83,7 @@ const defaultPreferences: Preferences = {
     showMaximize: true,
     showMore: true,
     styleType: 'chrome',
+    wheelable: true,
   },
   theme: {
     builtinType: 'default',

+ 2 - 0
packages/@core/preferences/src/types.ts

@@ -173,6 +173,8 @@ interface TabbarPreferences {
   showMore: boolean;
   /** 标签页风格 */
   styleType: TabsStyleType;
+  /** 是否开启鼠标滚轮响应 */
+  wheelable: boolean;
 }
 
 interface ThemePreferences {

+ 11 - 0
packages/@core/ui-kit/tabs-ui/src/tabs-view.vue

@@ -19,6 +19,7 @@ const props = withDefaults(defineProps<Props>(), {
   contentClass: 'vben-tabs-content',
   draggable: true,
   styleType: 'chrome',
+  wheelable: true,
 });
 
 const emit = defineEmits<TabsEmits>();
@@ -27,6 +28,7 @@ const forward = useForwardPropsEmits(props, emit);
 
 const {
   handleScrollAt,
+  handleWheel,
   scrollbarRef,
   scrollDirection,
   scrollIsAtLeft,
@@ -34,6 +36,14 @@ const {
   showScrollButton,
 } = useTabsViewScroll(props);
 
+function onWheel(e: WheelEvent) {
+  if (props.wheelable) {
+    handleWheel(e);
+    e.stopPropagation();
+    e.preventDefault();
+  }
+}
+
 useTabsDrag(props, emit);
 </script>
 
@@ -69,6 +79,7 @@ useTabsDrag(props, emit);
         shadow-left
         shadow-right
         @scroll-at="handleScrollAt"
+        @wheel="onWheel"
       >
         <TabsChrome
           v-if="styleType === 'chrome'"

+ 6 - 2
packages/@core/ui-kit/tabs-ui/src/types.ts

@@ -33,7 +33,6 @@ export interface TabsProps {
    * 仅限 tabs-chrome
    */
   maxWidth?: number;
-
   /**
    * @zh_CN tab最小宽度
    * 仅限 tabs-chrome
@@ -44,15 +43,20 @@ export interface TabsProps {
    * @zh_CN 是否显示图标
    */
   showIcon?: boolean;
+
   /**
    * @zh_CN 标签页风格
    */
   styleType?: TabsStyleType;
-
   /**
    * @zh_CN 选项卡数据
    */
   tabs?: TabDefinition[];
+
+  /**
+   * @zh_CN 是否响应滚轮事件
+   */
+  wheelable?: boolean;
 }
 
 export interface TabConfig extends TabDefinition {

+ 8 - 0
packages/@core/ui-kit/tabs-ui/src/use-tabs-view-scroll.ts

@@ -142,6 +142,13 @@ export function useTabsViewScroll(props: TabsProps) {
     scrollIsAtRight.value = right;
   }, 100);
 
+  function handleWheel({ deltaY }: WheelEvent) {
+    scrollViewportEl.value?.scrollBy({
+      behavior: 'smooth',
+      left: deltaY * 3,
+    });
+  }
+
   watch(
     () => props.active,
     async () => {
@@ -184,6 +191,7 @@ export function useTabsViewScroll(props: TabsProps) {
 
   return {
     handleScrollAt,
+    handleWheel,
     initScrollbar,
     scrollbarRef,
     scrollDirection,

+ 1 - 0
packages/effects/layouts/src/basic/tabbar/tabbar.vue

@@ -55,6 +55,7 @@ if (!preferences.tabbar.persist) {
     :show-icon="showIcon"
     :style-type="preferences.tabbar.styleType"
     :tabs="currentTabs"
+    :wheelable="preferences.tabbar.wheelable"
     @close="handleClose"
     @sort-tabs="tabbarStore.sortTabs"
     @unpin="unpinTab"

+ 8 - 0
packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue

@@ -18,6 +18,7 @@ const tabbarEnable = defineModel<boolean>('tabbarEnable');
 const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
 const tabbarPersist = defineModel<boolean>('tabbarPersist');
 const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
+const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
 const tabbarStyleType = defineModel<string>('tabbarStyleType');
 const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
 const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
@@ -53,6 +54,13 @@ const styleItems = computed((): SelectOption[] => [
   <SwitchItem v-model="tabbarDraggable" :disabled="!tabbarEnable">
     {{ $t('preferences.tabbar.draggable') }}
   </SwitchItem>
+  <SwitchItem
+    v-model="tabbarWheelable"
+    :disabled="!tabbarEnable"
+    :tip="$t('preferences.tabbar.wheelableTip')"
+  >
+    {{ $t('preferences.tabbar.wheelable') }}
+  </SwitchItem>
   <SwitchItem v-model="tabbarShowIcon" :disabled="!tabbarEnable">
     {{ $t('preferences.tabbar.icon') }}
   </SwitchItem>

+ 10 - 3
packages/effects/layouts/src/widgets/preferences/blocks/switch-item.vue

@@ -8,8 +8,9 @@ defineOptions({
   name: 'PreferenceSwitchItem',
 });
 
-withDefaults(defineProps<{ disabled?: boolean }>(), {
+withDefaults(defineProps<{ disabled?: boolean; tip?: string }>(), {
   disabled: false,
+  tip: '',
 });
 
 const checked = defineModel<boolean>();
@@ -32,11 +33,17 @@ function handleClick() {
     <span class="flex items-center text-sm">
       <slot></slot>
 
-      <VbenTooltip v-if="slots.tip" side="bottom">
+      <VbenTooltip v-if="slots.tip || tip" side="bottom">
         <template #trigger>
           <CircleHelp class="ml-1 size-3 cursor-help" />
         </template>
-        <slot name="tip"></slot>
+        <slot name="tip">
+          <template v-if="tip">
+            <p v-for="(line, index) in tip.split('\n')" :key="index">
+              {{ line }}
+            </p>
+          </template>
+        </slot>
       </VbenTooltip>
     </span>
     <span v-if="$slots.shortcut" class="ml-auto mr-2 text-xs opacity-60">

+ 2 - 0
packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue

@@ -105,6 +105,7 @@ const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
 const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
 const tabbarPersist = defineModel<boolean>('tabbarPersist');
 const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
+const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
 const tabbarStyleType = defineModel<string>('tabbarStyleType');
 
 const navigationStyleType = defineModel<NavigationStyleType>(
@@ -345,6 +346,7 @@ async function handleReset() {
                 v-model:tabbar-show-maximize="tabbarShowMaximize"
                 v-model:tabbar-show-more="tabbarShowMore"
                 v-model:tabbar-style-type="tabbarStyleType"
+                v-model:tabbar-wheelable="tabbarWheelable"
               />
             </Block>
             <Block :title="$t('preferences.widget.title')">

+ 2 - 0
packages/locales/src/langs/en-US/preferences.json

@@ -55,6 +55,8 @@
     "showMaximize": "Show Maximize Button",
     "persist": "Persist Tabs",
     "draggable": "Enable Draggable Sort",
+    "wheelable": "Support Mouse Wheel",
+    "wheelableTip": "When enabled, the Tabbar area responds to vertical scrolling events of the scroll wheel.",
     "styleType": {
       "title": "Tabs Style",
       "chrome": "Chrome",

+ 2 - 0
packages/locales/src/langs/zh-CN/preferences.json

@@ -55,6 +55,8 @@
     "showMaximize": "显示最大化按钮",
     "persist": "持久化标签页",
     "draggable": "启动拖拽排序",
+    "wheelable": "启用纵向滚轮响应",
+    "wheelableTip": "开启后,标签栏区域可以响应滚轮的纵向滚动事件。\n关闭时,只能响应系统的横向滚动事件(需要按下Shift再滚动滚轮)",
     "styleType": {
       "title": "标签页风格",
       "chrome": "谷歌",