Skip to content

Commit 4738534

Browse files
committed
refactor: tabs #6288
1 parent 6240ab2 commit 4738534

File tree

13 files changed

+1008
-793
lines changed

13 files changed

+1008
-793
lines changed

components/tabs/index.en-US.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
category: Components
33
type: Data Display
44
title: Tabs
5-
cover: https://gw.alipayobjects.com/zos/antfincdn/lkI2hNEDr2V/Tabs.svg
5+
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*72NDQqXkyOEAAAAAAAAAAAAADrJ8AQ/original
66
---
77

88
Tabs make it easy to switch between different views.
@@ -25,7 +25,7 @@ Ant Design has 3 types of Tabs for different situations.
2525
| animated | Whether to change tabs with animation. Only works while tabPosition=`"top"` \| `"bottom"` | boolean \| {inkBar:boolean, tabPane:boolean} | `true`, `false` when `type="card"` | |
2626
| destroyInactiveTabPane | Whether destroy inactive TabPane when change tab | boolean | false | |
2727
| hideAdd | Hide plus icon or not. Only works while `type="editable-card"` | boolean | `false` | } |
28-
| size | preset tab bar size | `large` \| `default` \| `small` | `default` | |
28+
| size | preset tab bar size | `large` \| `middle` \| `small` | `middle` | |
2929
| tabBarGutter | The gap between tabs | number | - | |
3030
| tabBarStyle | Tab bar style object | CSSProperties | - | |
3131
| tabPosition | Position of tabs | `top` \| `right` \| `bottom` \| `left` | `top` | |

components/tabs/index.zh-CN.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ category: Components
33
subtitle: 标签页
44
type: 数据展示
55
title: Tabs
6-
cover: https://gw.alipayobjects.com/zos/antfincdn/lkI2hNEDr2V/Tabs.svg
6+
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*72NDQqXkyOEAAAAAAAAAAAAADrJ8AQ/original
77
---
88

99
选项卡切换组件。
@@ -29,7 +29,7 @@ Ant Design 依次提供了三级选项卡,分别用于不同的场景。
2929
| centered | 标签居中展示 | boolean | false | 3.0 | |
3030
| destroyInactiveTabPane | 被隐藏时是否销毁 DOM 结构 | boolean | false | | |
3131
| hideAdd | 是否隐藏加号图标,在 `type="editable-card"` 时有效 | boolean | false | | |
32-
| size | 大小,提供 `large` `default``small` 三种大小 | string | `default` | | |
32+
| size | 大小,提供 `large` `middle``small` 三种大小 | string | `middle` | | |
3333
| tabBarGutter | tabs 之间的间隙 | number || | |
3434
| tabBarStyle | tab bar 的样式对象 | CSSProperties | - | | |
3535
| tabPosition | 页签位置,可选值有 `top` `right` `bottom` `left` | string | `top` | | |

components/tabs/src/TabNavList/OperationNode.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import Dropdown from '../../../vc-dropdown';
33
import type { Tab, TabsLocale, EditableConfig } from '../interface';
44
import AddButton from './AddButton';
55
import type { Key } from '../../../_util/type';
6+
import { functionType } from '../../../_util/type';
67
import KeyCode from '../../../_util/KeyCode';
78
import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
89
import classNames from '../../../_util/classNames';
910
import { defineComponent, watch, computed, onMounted } from 'vue';
1011
import PropTypes from '../../../_util/vue-types';
1112
import useState from '../../../_util/hooks/useState';
1213
import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
14+
import { useProvideOverride } from '../../../menu/src/OverrideContext';
1315

1416
export const operationNodeProps = {
1517
prefixCls: { type: String },
@@ -25,6 +27,10 @@ export const operationNodeProps = {
2527
locale: { type: Object as PropType<TabsLocale>, default: undefined as TabsLocale },
2628
removeAriaLabel: String,
2729
onTabClick: { type: Function as PropType<(key: Key, e: MouseEvent | KeyboardEvent) => void> },
30+
popupClassName: String,
31+
getPopupContainer: functionType<
32+
((triggerNode?: HTMLElement | undefined) => HTMLElement) | undefined
33+
>(),
2834
};
2935

3036
export type OperationNodeProps = Partial<ExtractPropTypes<typeof operationNodeProps>>;
@@ -117,7 +123,7 @@ export default defineComponent({
117123
setSelectedKey(null);
118124
}
119125
});
120-
126+
useProvideOverride({});
121127
return () => {
122128
const {
123129
prefixCls,
@@ -131,6 +137,7 @@ export default defineComponent({
131137
tabBarGutter,
132138
rtl,
133139
onTabClick,
140+
popupClassName,
134141
} = props;
135142
const dropdownPrefix = `${prefixCls}-dropdown`;
136143

@@ -147,17 +154,19 @@ export default defineComponent({
147154

148155
const overlayClassName = classNames({
149156
[`${dropdownPrefix}-rtl`]: rtl,
157+
[`${popupClassName}`]: true,
150158
});
151159
const moreNode = mobile ? null : (
152160
<Dropdown
153161
prefixCls={dropdownPrefix}
154162
trigger={['hover']}
155-
visible={open.value}
163+
open={open.value}
156164
transitionName={moreTransitionName}
157-
onVisibleChange={setOpen}
165+
onOpenChange={setOpen}
158166
overlayClassName={overlayClassName}
159167
mouseEnterDelay={0.1}
160168
mouseLeaveDelay={0.1}
169+
getPopupContainer={props.getPopupContainer}
161170
v-slots={{
162171
overlay: () => (
163172
<Menu

components/tabs/src/TabNavList/index.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useInjectTabs } from '../TabContext';
1717
import useTouchMove from '../hooks/useTouchMove';
1818
import AddButton from './AddButton';
1919
import type { Key } from '../../../_util/type';
20+
import { objectType, functionType } from '../../../_util/type';
2021
import type { ExtractPropTypes, PropType, CSSProperties } from 'vue';
2122
import { onBeforeUnmount, defineComponent, ref, watch, watchEffect, computed } from 'vue';
2223
import PropTypes from '../../../_util/vue-types';
@@ -36,14 +37,18 @@ export const tabNavListProps = () => {
3637
tabPosition: { type: String as PropType<TabPosition> },
3738
activeKey: { type: [String, Number] },
3839
rtl: { type: Boolean },
39-
animated: { type: Object as PropType<AnimatedConfig>, default: undefined as AnimatedConfig },
40-
editable: { type: Object as PropType<EditableConfig> },
40+
animated: objectType<AnimatedConfig>(),
41+
editable: objectType<EditableConfig>(),
4142
moreIcon: PropTypes.any,
4243
moreTransitionName: { type: String },
4344
mobile: { type: Boolean },
4445
tabBarGutter: { type: Number },
4546
renderTabBar: { type: Function as PropType<RenderTabBar> },
46-
locale: { type: Object as PropType<TabsLocale>, default: undefined as TabsLocale },
47+
locale: objectType<TabsLocale>(),
48+
popupClassName: String,
49+
getPopupContainer: functionType<
50+
((triggerNode?: HTMLElement | undefined) => HTMLElement) | undefined
51+
>(),
4752
onTabClick: {
4853
type: Function as PropType<(activeKey: Key, e: MouseEvent | KeyboardEvent) => void>,
4954
},

components/tabs/src/Tabs.tsx

+36-26
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
OnTabScroll,
1111
Tab,
1212
} from './interface';
13-
import type { CSSProperties, PropType, ExtractPropTypes } from 'vue';
13+
import type { CSSProperties, ExtractPropTypes } from 'vue';
1414
import { defineComponent, computed, onMounted, watchEffect, camelize } from 'vue';
1515
import { flattenChildren, initDefaultProps, isValidElement } from '../../_util/props-util';
1616
import useConfigInject from '../../config-provider/hooks/useConfigInject';
@@ -24,6 +24,14 @@ import devWarning from '../../vc-util/devWarning';
2424
import type { SizeType } from '../../config-provider';
2525
import { useProvideTabs } from './TabContext';
2626
import type { Key } from '../../_util/type';
27+
import {
28+
arrayType,
29+
stringType,
30+
someType,
31+
functionType,
32+
objectType,
33+
booleanType,
34+
} from '../../_util/type';
2735
import pick from 'lodash-es/pick';
2836
import PropTypes from '../../_util/vue-types';
2937
import type { MouseEventHandler } from '../../_util/EventInterface';
@@ -39,36 +47,33 @@ export const tabsProps = () => {
3947
return {
4048
prefixCls: { type: String },
4149
id: { type: String },
42-
50+
popupClassName: String,
51+
getPopupContainer: functionType<
52+
((triggerNode?: HTMLElement | undefined) => HTMLElement) | undefined
53+
>(),
4354
activeKey: { type: [String, Number] },
4455
defaultActiveKey: { type: [String, Number] },
45-
direction: { type: String as PropType<'ltr' | 'rtl'> },
46-
animated: { type: [Boolean, Object] as PropType<boolean | AnimatedConfig> },
47-
renderTabBar: { type: Function as PropType<RenderTabBar> },
56+
direction: stringType<'ltr' | 'rtl'>(),
57+
animated: someType<boolean | AnimatedConfig>([Boolean, Object]),
58+
renderTabBar: functionType<RenderTabBar>(),
4859
tabBarGutter: { type: Number },
49-
tabBarStyle: { type: Object as PropType<CSSProperties> },
50-
tabPosition: { type: String as PropType<TabPosition> },
51-
destroyInactiveTabPane: { type: Boolean },
60+
tabBarStyle: objectType<CSSProperties>(),
61+
tabPosition: stringType<TabPosition>(),
62+
destroyInactiveTabPane: booleanType(),
5263

5364
hideAdd: Boolean,
54-
type: { type: String as PropType<TabsType> },
55-
size: { type: String as PropType<SizeType> },
65+
type: stringType<TabsType>(),
66+
size: stringType<SizeType>(),
5667
centered: Boolean,
57-
onEdit: {
58-
type: Function as PropType<
59-
(e: MouseEvent | KeyboardEvent | Key, action: 'add' | 'remove') => void
60-
>,
61-
},
62-
onChange: { type: Function as PropType<(activeKey: Key) => void> },
63-
onTabClick: {
64-
type: Function as PropType<(activeKey: Key, e: KeyboardEvent | MouseEvent) => void>,
65-
},
66-
onTabScroll: { type: Function as PropType<OnTabScroll> },
67-
'onUpdate:activeKey': { type: Function as PropType<(activeKey: Key) => void> },
68+
onEdit: functionType<(e: MouseEvent | KeyboardEvent | Key, action: 'add' | 'remove') => void>(),
69+
onChange: functionType<(activeKey: Key) => void>(),
70+
onTabClick: functionType<(activeKey: Key, e: KeyboardEvent | MouseEvent) => void>(),
71+
onTabScroll: functionType<OnTabScroll>(),
72+
'onUpdate:activeKey': functionType<(activeKey: Key) => void>(),
6873
// Accessibility
69-
locale: { type: Object as PropType<TabsLocale>, default: undefined as TabsLocale },
70-
onPrevClick: Function as PropType<MouseEventHandler>,
71-
onNextClick: Function as PropType<MouseEventHandler>,
74+
locale: objectType<TabsLocale>(),
75+
onPrevClick: functionType<MouseEventHandler>(),
76+
onNextClick: functionType<MouseEventHandler>(),
7277
tabBarExtraContent: PropTypes.any,
7378
};
7479
};
@@ -126,7 +131,7 @@ const InternalTabs = defineComponent({
126131
tabPane: false,
127132
},
128133
}),
129-
tabs: { type: Array as PropType<Tab[]> },
134+
tabs: arrayType<Tab[]>(),
130135
},
131136
slots: [
132137
'tabBarExtraContent',
@@ -154,7 +159,10 @@ const InternalTabs = defineComponent({
154159
'Tabs',
155160
'`tabBarExtraContent` slot is deprecated. Please use `rightExtra` slot instead.',
156161
);
157-
const { prefixCls, direction, size, rootPrefixCls } = useConfigInject('tabs', props);
162+
const { prefixCls, direction, size, rootPrefixCls, getPopupContainer } = useConfigInject(
163+
'tabs',
164+
props,
165+
);
158166
const [wrapSSR, hashId] = useStyle(prefixCls);
159167
const rtl = computed(() => direction.value === 'rtl');
160168
const mergedAnimated = computed<AnimatedConfig>(() => {
@@ -284,6 +292,8 @@ const InternalTabs = defineComponent({
284292
onTabClick: onInternalTabClick,
285293
onTabScroll,
286294
style: tabBarStyle,
295+
getPopupContainer: getPopupContainer.value,
296+
popupClassName: classNames(props.popupClassName, hashId.value),
287297
};
288298

289299
if (renderTabBar) {

components/tabs/style/card.tsx

-101
This file was deleted.

0 commit comments

Comments
 (0)