mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-01-23 01:30:26 +08:00
feat: tabbar support mouse wheel vertical (#5129)
* feat: tabbar support mouse wheel * docs: add tabbar wheelable tips * chore: resolve vitest test
This commit is contained in:
parent
be208fe915
commit
7fbf7b189a
@ -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",
|
||||
|
@ -83,6 +83,7 @@ const defaultPreferences: Preferences = {
|
||||
showMaximize: true,
|
||||
showMore: true,
|
||||
styleType: 'chrome',
|
||||
wheelable: true,
|
||||
},
|
||||
theme: {
|
||||
builtinType: 'default',
|
||||
|
@ -173,6 +173,8 @@ interface TabbarPreferences {
|
||||
showMore: boolean;
|
||||
/** 标签页风格 */
|
||||
styleType: TabsStyleType;
|
||||
/** 是否开启鼠标滚轮响应 */
|
||||
wheelable: boolean;
|
||||
}
|
||||
|
||||
interface ThemePreferences {
|
||||
|
@ -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'"
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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')">
|
||||
|
@ -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",
|
||||
|
@ -55,6 +55,8 @@
|
||||
"showMaximize": "显示最大化按钮",
|
||||
"persist": "持久化标签页",
|
||||
"draggable": "启动拖拽排序",
|
||||
"wheelable": "启用纵向滚轮响应",
|
||||
"wheelableTip": "开启后,标签栏区域可以响应滚轮的纵向滚动事件。\n关闭时,只能响应系统的横向滚动事件(需要按下Shift再滚动滚轮)",
|
||||
"styleType": {
|
||||
"title": "标签页风格",
|
||||
"chrome": "谷歌",
|
||||
|
Loading…
Reference in New Issue
Block a user