From 75cf2640402f9eace9dcfa97cfd562ff332c19ce Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Thu, 7 Oct 2021 09:23:36 +0800 Subject: [PATCH] refactor: tabs & card (#4732) * refactor: tabs * refactor: tabs * fix: tabs hotreload error * refactor: rename useRef * feat: add leftExtra rightExtra * refactor: tabs * test: update tabs test * refactor: card * doc: update tabs demo * refactor: add card style * style: update vue dep --- components/_util/hooks/useRef.ts | 17 - components/_util/hooks/useRefs.ts | 20 + components/_util/hooks/useState.ts | 2 +- components/card/Card.tsx | 308 ++--- components/card/Grid.tsx | 35 +- components/card/Meta.tsx | 77 +- .../__tests__/__snapshots__/demo.test.js.snap | 124 +- .../__snapshots__/index.test.js.snap | 2 +- components/card/demo/tabs.vue | 7 +- components/card/index.en-US.md | 16 +- components/card/index.zh-CN.md | 16 +- components/card/style/index.less | 69 +- components/card/style/{index.ts => index.tsx} | 0 components/card/style/size.less | 5 - components/components.ts | 3 +- .../__tests__/__snapshots__/demo.test.js.snap | 2 +- components/menu/src/Menu.tsx | 2 + components/menu/src/MenuItem.tsx | 2 + .../__tests__/__snapshots__/demo.test.js.snap | 244 ++-- components/page-header/demo/responsive.vue | 14 +- components/rate/index.tsx | 8 +- components/style/themes/default.less | 37 +- components/tabs/TabBar.tsx | 94 -- .../__tests__/__snapshots__/demo.test.js.snap | 1148 +++++++++-------- .../__snapshots__/index.test.js.snap | 34 +- components/tabs/__tests__/index.test.js | 4 +- components/tabs/demo/card-top.vue | 63 +- components/tabs/demo/centered.vue | 36 + components/tabs/demo/custom-add-trigger.vue | 2 +- components/tabs/demo/custom-tab-bar.vue | 6 +- components/tabs/demo/extra.vue | 17 +- components/tabs/demo/index.vue | 3 + components/tabs/demo/position.vue | 28 +- components/tabs/demo/slide.vue | 5 +- components/tabs/index.en-US.md | 41 +- components/tabs/index.ts | 10 +- components/tabs/index.zh-CN.md | 55 +- components/tabs/src/TabContext.ts | 33 + components/tabs/src/TabNavList/AddButton.tsx | 48 + .../tabs/src/TabNavList/OperationNode.tsx | 218 ++++ components/tabs/src/TabNavList/TabNode.tsx | 138 ++ components/tabs/src/TabNavList/index.tsx | 542 ++++++++ components/tabs/src/TabPanelList/TabPane.tsx | 85 ++ components/tabs/src/TabPanelList/index.tsx | 66 + components/tabs/src/Tabs.tsx | 357 +++++ components/tabs/src/hooks/useOffsets.ts | 40 + components/tabs/src/hooks/useRaf.ts | 52 + components/tabs/src/hooks/useSyncState.ts | 21 + components/tabs/src/hooks/useTouchMove.ts | 140 ++ components/tabs/src/index.ts | 11 + components/tabs/src/interface.ts | 48 + components/tabs/style/card-style.less | 186 --- components/tabs/style/card.less | 97 ++ components/tabs/style/dropdown.less | 60 + components/tabs/style/index.less | 569 +++----- components/tabs/style/{index.ts => index.tsx} | 0 components/tabs/style/position.less | 195 +++ components/tabs/style/rtl.less | 79 ++ components/tabs/style/size.less | 41 + components/tabs/tabs.tsx | 181 --- components/vc-overflow/Overflow.tsx | 3 + components/vc-overflow/RawItem.tsx | 1 + components/vc-picker/PickerTrigger.tsx | 2 +- .../vc-picker/panels/DatetimePanel/index.tsx | 2 +- .../panels/TimePanel/TimeUnitColumn.tsx | 4 +- .../vc-picker/panels/TimePanel/index.tsx | 2 +- components/vc-progress/src/Circle.tsx | 6 +- components/vc-progress/src/Line.tsx | 6 +- components/vc-progress/src/common.ts | 9 +- components/vc-tabs/src/InkTabBar.jsx | 22 - components/vc-tabs/src/InkTabBarNode.jsx | 121 -- components/vc-tabs/src/KeyCode.js | 18 - components/vc-tabs/src/SaveRef.jsx | 27 - .../vc-tabs/src/ScrollableInkTabBar.jsx | 26 - components/vc-tabs/src/ScrollableTabBar.jsx | 20 - .../vc-tabs/src/ScrollableTabBarNode.jsx | 335 ----- components/vc-tabs/src/Sentinel.jsx | 44 - components/vc-tabs/src/TabBar.jsx | 19 - components/vc-tabs/src/TabBarRootNode.jsx | 61 - components/vc-tabs/src/TabBarTabsNode.jsx | 83 -- components/vc-tabs/src/TabContent.jsx | 92 -- components/vc-tabs/src/TabPane.jsx | 53 - components/vc-tabs/src/Tabs.jsx | 254 ---- components/vc-tabs/src/index.js | 7 - components/vc-tabs/src/utils.js | 132 -- components/vc-util/Dom/scrollLocker.ts | 2 +- site/debugger/index.tsx | 2 +- tests/__snapshots__/index.test.js.snap | 1 - 88 files changed, 3797 insertions(+), 3320 deletions(-) delete mode 100644 components/_util/hooks/useRef.ts create mode 100644 components/_util/hooks/useRefs.ts rename components/card/style/{index.ts => index.tsx} (100%) delete mode 100644 components/tabs/TabBar.tsx create mode 100644 components/tabs/demo/centered.vue create mode 100644 components/tabs/src/TabContext.ts create mode 100644 components/tabs/src/TabNavList/AddButton.tsx create mode 100644 components/tabs/src/TabNavList/OperationNode.tsx create mode 100644 components/tabs/src/TabNavList/TabNode.tsx create mode 100644 components/tabs/src/TabNavList/index.tsx create mode 100644 components/tabs/src/TabPanelList/TabPane.tsx create mode 100644 components/tabs/src/TabPanelList/index.tsx create mode 100644 components/tabs/src/Tabs.tsx create mode 100644 components/tabs/src/hooks/useOffsets.ts create mode 100644 components/tabs/src/hooks/useRaf.ts create mode 100644 components/tabs/src/hooks/useSyncState.ts create mode 100644 components/tabs/src/hooks/useTouchMove.ts create mode 100644 components/tabs/src/index.ts create mode 100644 components/tabs/src/interface.ts delete mode 100644 components/tabs/style/card-style.less create mode 100644 components/tabs/style/card.less create mode 100644 components/tabs/style/dropdown.less rename components/tabs/style/{index.ts => index.tsx} (100%) create mode 100644 components/tabs/style/position.less create mode 100644 components/tabs/style/rtl.less create mode 100644 components/tabs/style/size.less delete mode 100644 components/tabs/tabs.tsx delete mode 100644 components/vc-tabs/src/InkTabBar.jsx delete mode 100644 components/vc-tabs/src/InkTabBarNode.jsx delete mode 100644 components/vc-tabs/src/KeyCode.js delete mode 100644 components/vc-tabs/src/SaveRef.jsx delete mode 100644 components/vc-tabs/src/ScrollableInkTabBar.jsx delete mode 100644 components/vc-tabs/src/ScrollableTabBar.jsx delete mode 100644 components/vc-tabs/src/ScrollableTabBarNode.jsx delete mode 100644 components/vc-tabs/src/Sentinel.jsx delete mode 100644 components/vc-tabs/src/TabBar.jsx delete mode 100644 components/vc-tabs/src/TabBarRootNode.jsx delete mode 100644 components/vc-tabs/src/TabBarTabsNode.jsx delete mode 100644 components/vc-tabs/src/TabContent.jsx delete mode 100644 components/vc-tabs/src/TabPane.jsx delete mode 100644 components/vc-tabs/src/Tabs.jsx delete mode 100755 components/vc-tabs/src/index.js delete mode 100644 components/vc-tabs/src/utils.js diff --git a/components/_util/hooks/useRef.ts b/components/_util/hooks/useRef.ts deleted file mode 100644 index 86f6512ec..000000000 --- a/components/_util/hooks/useRef.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Ref } from 'vue'; -import { onBeforeUpdate, ref } from 'vue'; - -export type UseRef = [(el: any, key: string | number) => void, Ref]; -export type Refs = Record; -export const useRef = (): UseRef => { - const refs = ref({}); - const setRef = (el: any, key: string | number) => { - refs.value[key] = el; - }; - onBeforeUpdate(() => { - refs.value = {}; - }); - return [setRef, refs]; -}; - -export default useRef; diff --git a/components/_util/hooks/useRefs.ts b/components/_util/hooks/useRefs.ts new file mode 100644 index 000000000..965805e20 --- /dev/null +++ b/components/_util/hooks/useRefs.ts @@ -0,0 +1,20 @@ +import type { Ref, ComponentPublicInstance } from 'vue'; +import { onBeforeUpdate, ref } from 'vue'; +import type { Key } from '../type'; + +type RefType = HTMLElement | ComponentPublicInstance; +export type RefsValue = Map; +type UseRef = [(key: Key) => (el: RefType) => void, Ref]; +const useRefs = (): UseRef => { + const refs = ref(new Map()); + + const setRef = (key: Key) => (el: RefType) => { + refs.value.set(key, el); + }; + onBeforeUpdate(() => { + refs.value = new Map(); + }); + return [setRef, refs]; +}; + +export default useRefs; diff --git a/components/_util/hooks/useState.ts b/components/_util/hooks/useState.ts index a74476a9e..5276ab44a 100644 --- a/components/_util/hooks/useState.ts +++ b/components/_util/hooks/useState.ts @@ -2,7 +2,7 @@ import type { Ref } from 'vue'; import { ref } from 'vue'; export default function useState>( - defaultStateValue: T | (() => T), + defaultStateValue?: T | (() => T), ): [R, (val: T) => void] { const initValue: T = typeof defaultStateValue === 'function' ? (defaultStateValue as any)() : defaultStateValue; diff --git a/components/card/Card.tsx b/components/card/Card.tsx index 88d1d5159..e968d7999 100644 --- a/components/card/Card.tsx +++ b/components/card/Card.tsx @@ -1,68 +1,62 @@ import type { VNodeTypes, PropType, VNode, ExtractPropTypes } from 'vue'; -import { inject, isVNode, defineComponent } from 'vue'; -import { tuple } from '../_util/type'; +import { isVNode, defineComponent, renderSlot } from 'vue'; import Tabs from '../tabs'; import Row from '../row'; import Col from '../col'; import PropTypes from '../_util/vue-types'; -import { getComponent, getSlot, isEmptyElement } from '../_util/props-util'; +import { flattenChildren, isEmptyElement } from '../_util/props-util'; import BaseMixin from '../_util/BaseMixin'; -import { defaultConfigProvider } from '../config-provider'; +import type { SizeType } from '../config-provider'; import isPlainObject from 'lodash-es/isPlainObject'; - +import useConfigInject from '../_util/hooks/useConfigInject'; +import devWarning from '../vc-util/devWarning'; export interface CardTabListType { key: string; - tab: VNodeTypes; + tab: any; + /** @deprecated Please use `customTab` instead. */ slots?: { tab: string }; disabled?: boolean; } export type CardType = 'inner'; +export type CardSize = 'default' | 'small'; const { TabPane } = Tabs; -const cardProps = { +const cardProps = () => ({ prefixCls: PropTypes.string, - title: PropTypes.VNodeChild, - extra: PropTypes.VNodeChild, + title: PropTypes.any, + extra: PropTypes.any, bordered: PropTypes.looseBool.def(true), bodyStyle: PropTypes.style, headStyle: PropTypes.style, loading: PropTypes.looseBool.def(false), hoverable: PropTypes.looseBool.def(false), - type: PropTypes.string, - size: PropTypes.oneOf(tuple('default', 'small')), - actions: PropTypes.VNodeChild, + type: { type: String as PropType }, + size: { type: String as PropType }, + actions: PropTypes.any, tabList: { type: Array as PropType, }, - tabBarExtraContent: PropTypes.VNodeChild, + tabBarExtraContent: PropTypes.any, activeTabKey: PropTypes.string, defaultActiveTabKey: PropTypes.string, - cover: PropTypes.VNodeChild, + cover: PropTypes.any, onTabChange: { type: Function as PropType<(key: string) => void>, }, -}; +}); -export type CardProps = Partial>; +export type CardProps = Partial>>; const Card = defineComponent({ name: 'ACard', mixins: [BaseMixin], - props: cardProps, - setup() { - return { - configProvider: inject('configProvider', defaultConfigProvider), - }; - }, - data() { - return { - widerPadding: false, - }; - }, - methods: { - getAction(actions: VNodeTypes[]) { + props: cardProps(), + slots: ['title', 'extra', 'tabBarExtraContent', 'actions', 'cover', 'customTab'], + setup(props, { slots }) { + const { prefixCls, direction, size } = useConfigInject('card', props); + const getAction = (actions: VNodeTypes[]) => { const actionList = actions.map((action, index) => (isVNode(action) && !isEmptyElement(action)) || !isVNode(action) ? (
  • @@ -71,11 +65,11 @@ const Card = defineComponent({ ) : null, ); return actionList; - }, - triggerTabChange(key: string) { - this.$emit('tabChange', key); - }, - isContainGrid(obj: VNode[] = []) { + }; + const triggerTabChange = (key: string) => { + props.onTabChange?.(key); + }; + const isContainGrid = (obj: VNode[] = []) => { let containGrid: boolean; obj.forEach(element => { if (element && isPlainObject(element.type) && (element.type as any).__ANT_CARD_GRID) { @@ -83,145 +77,129 @@ const Card = defineComponent({ } }); return containGrid; - }, - }, - render() { - const { - prefixCls: customizePrefixCls, - headStyle = {}, - bodyStyle = {}, - loading, - bordered = true, - size = 'default', - type, - tabList, - hoverable, - activeTabKey, - defaultActiveTabKey, - } = this.$props; - const { $slots } = this; - const children = getSlot(this); - const { getPrefixCls } = this.configProvider; - const prefixCls = getPrefixCls('card', customizePrefixCls); - - const tabBarExtraContent = getComponent(this, 'tabBarExtraContent'); - const classString = { - [`${prefixCls}`]: true, - [`${prefixCls}-loading`]: loading, - [`${prefixCls}-bordered`]: bordered, - [`${prefixCls}-hoverable`]: !!hoverable, - [`${prefixCls}-contain-grid`]: this.isContainGrid(children), - [`${prefixCls}-contain-tabs`]: tabList && tabList.length, - [`${prefixCls}-${size}`]: size !== 'default', - [`${prefixCls}-type-${type}`]: !!type, }; - const loadingBlockStyle = - bodyStyle.padding === 0 || bodyStyle.padding === '0px' ? { padding: 24 } : undefined; + return () => { + const { + headStyle = {}, + bodyStyle = {}, + loading, + bordered = true, + type, + tabList, + hoverable, + activeTabKey, + defaultActiveTabKey, + tabBarExtraContent = slots.tabBarExtraContent?.(), + title = slots.title?.(), + extra = slots.extra?.(), + actions = slots.actions?.(), + cover = slots.cover?.(), + } = props; + const children = flattenChildren(slots.default?.()); + const pre = prefixCls.value; + const classString = { + [`${pre}`]: true, + [`${pre}-loading`]: loading, + [`${pre}-bordered`]: bordered, + [`${pre}-hoverable`]: !!hoverable, + [`${pre}-contain-grid`]: isContainGrid(children), + [`${pre}-contain-tabs`]: tabList && tabList.length, + [`${pre}-${size.value}`]: size.value, + [`${pre}-type-${type}`]: !!type, + [`${pre}-rtl`]: direction.value === 'rtl', + }; - const loadingBlock = ( -
    - - -
    - - - - -
    - - -
    - - - - -
    - - -
    - - - - -
    - - -
    - - - - -
    - - -
    - - -
    - - -
    - ); + const loadingBlockStyle = + bodyStyle.padding === 0 || bodyStyle.padding === '0px' ? { padding: '24px' } : undefined; - const hasActiveTabKey = activeTabKey !== undefined; - const tabsProps = { - size: 'large', - [hasActiveTabKey ? 'activeKey' : 'defaultActiveKey']: hasActiveTabKey - ? activeTabKey - : defaultActiveTabKey, - tabBarExtraContent, - onChange: this.triggerTabChange, - class: `${prefixCls}-head-tabs`, - }; - - let head; - const tabs = - tabList && tabList.length ? ( - - {tabList.map(item => { - const { tab: temp, slots } = item as CardTabListType; - const name = slots?.tab; - const tab = temp !== undefined ? temp : $slots[name] ? $slots[name](item) : null; - return ; - })} - - ) : null; - const titleDom = getComponent(this, 'title'); - const extraDom = getComponent(this, 'extra'); - if (titleDom || extraDom || tabs) { - head = ( -
    -
    - {titleDom &&
    {titleDom}
    } - {extraDom &&
    {extraDom}
    } -
    - {tabs} + const block =
    ; + const loadingBlock = ( +
    + + {block} + + + {block} + {block} + + + {block} + {block} + + + {block} + {block} + + + {block} + {block} + {block} +
    ); - } - const cover = getComponent(this, 'cover'); - const coverDom = cover ?
    {cover}
    : null; - const body = ( -
    - {loading ? loadingBlock : children} -
    - ); - const actions = getComponent(this, 'actions'); - const actionDom = - actions && actions.length ? ( -
      {this.getAction(actions)}
    - ) : null; + const hasActiveTabKey = activeTabKey !== undefined; + const tabsProps = { + size: 'large' as SizeType, + [hasActiveTabKey ? 'activeKey' : 'defaultActiveKey']: hasActiveTabKey + ? activeTabKey + : defaultActiveTabKey, + onChange: triggerTabChange, + class: `${pre}-head-tabs`, + }; - return ( -
    - {head} - {coverDom} - {children ? body : null} - {actionDom} -
    - ); + let head; + const tabs = + tabList && tabList.length ? ( + tabBarExtraContent : null }} + > + {tabList.map(item => { + const { tab: temp, slots: itemSlots } = item as CardTabListType; + const name = itemSlots?.tab; + devWarning( + !itemSlots, + 'Card', + `tabList slots is deprecated, Please use \`customTab\` instead.`, + ); + let tab = temp !== undefined ? temp : slots[name] ? slots[name](item) : null; + tab = renderSlot(slots, 'customTab', item as any, () => [tab]); + return ; + })} + + ) : null; + if (title || extra || tabs) { + head = ( +
    +
    + {title &&
    {title}
    } + {extra &&
    {extra}
    } +
    + {tabs} +
    + ); + } + + const coverDom = cover ?
    {cover}
    : null; + const body = ( +
    + {loading ? loadingBlock : children} +
    + ); + const actionDom = + actions && actions.length ?
      {getAction(actions)}
    : null; + + return ( +
    + {head} + {coverDom} + {children && children.length ? body : null} + {actionDom} +
    + ); + }; }, }); diff --git a/components/card/Grid.tsx b/components/card/Grid.tsx index c5692703a..ba4156b9d 100644 --- a/components/card/Grid.tsx +++ b/components/card/Grid.tsx @@ -1,30 +1,23 @@ -import { defineComponent, inject } from 'vue'; -import PropTypes from '../_util/vue-types'; -import { defaultConfigProvider } from '../config-provider'; -import { getSlot } from '../_util/props-util'; +import { defineComponent, computed } from 'vue'; +import useConfigInject from '../_util/hooks/useConfigInject'; export default defineComponent({ name: 'ACardGrid', __ANT_CARD_GRID: true, props: { - prefixCls: PropTypes.string, - hoverable: PropTypes.looseBool, + prefixCls: String, + hoverable: { type: Boolean, default: true }, }, - setup() { - return { - configProvider: inject('configProvider', defaultConfigProvider), + setup(props, { slots }) { + const { prefixCls } = useConfigInject('card', props); + const classNames = computed(() => { + return { + [`${prefixCls.value}-grid`]: true, + [`${prefixCls.value}-grid-hoverable`]: props.hoverable, + }; + }); + return () => { + return
    {slots.default?.()}
    ; }; }, - render() { - const { prefixCls: customizePrefixCls, hoverable = true } = this.$props; - - const { getPrefixCls } = this.configProvider; - const prefixCls = getPrefixCls('card', customizePrefixCls); - - const classString = { - [`${prefixCls}-grid`]: true, - [`${prefixCls}-grid-hoverable`]: hoverable, - }; - return
    {getSlot(this)}
    ; - }, }); diff --git a/components/card/Meta.tsx b/components/card/Meta.tsx index f72238e1a..af2f13d26 100644 --- a/components/card/Meta.tsx +++ b/components/card/Meta.tsx @@ -1,52 +1,47 @@ -import { defineComponent, inject } from 'vue'; +import { defineComponent } from 'vue'; import PropTypes from '../_util/vue-types'; -import { getComponent } from '../_util/props-util'; -import { defaultConfigProvider } from '../config-provider'; +import { getPropsSlot } from '../_util/props-util'; +import useConfigInject from '../_util/hooks/useConfigInject'; export default defineComponent({ name: 'ACardMeta', props: { prefixCls: PropTypes.string, - title: PropTypes.VNodeChild, - description: PropTypes.VNodeChild, - avatar: PropTypes.VNodeChild, + title: PropTypes.any, + description: PropTypes.any, + avatar: PropTypes.any, }, - setup() { - return { - configProvider: inject('configProvider', defaultConfigProvider), - }; - }, - render() { - const { prefixCls: customizePrefixCls } = this.$props; + slots: ['title', 'description', 'avatar'], + setup(props, { slots }) { + const { prefixCls } = useConfigInject('card', props); + return () => { + const classString = { + [`${prefixCls.value}-meta`]: true, + }; + const avatar = getPropsSlot(slots, props, 'avatar'); + const title = getPropsSlot(slots, props, 'title'); + const description = getPropsSlot(slots, props, 'description'); - const { getPrefixCls } = this.configProvider; - const prefixCls = getPrefixCls('card', customizePrefixCls); - - const classString = { - [`${prefixCls}-meta`]: true, - }; - - const avatar = getComponent(this, 'avatar'); - const title = getComponent(this, 'title'); - const description = getComponent(this, 'description'); - - const avatarDom = avatar ?
    {avatar}
    : null; - const titleDom = title ?
    {title}
    : null; - const descriptionDom = description ? ( -
    {description}
    - ) : null; - const MetaDetail = - titleDom || descriptionDom ? ( -
    - {titleDom} - {descriptionDom} -
    + const avatarDom = avatar ? ( +
    {avatar}
    ) : null; - return ( -
    - {avatarDom} - {MetaDetail} -
    - ); + const titleDom = title ?
    {title}
    : null; + const descriptionDom = description ? ( +
    {description}
    + ) : null; + const MetaDetail = + titleDom || descriptionDom ? ( +
    + {titleDom} + {descriptionDom} +
    + ) : null; + return ( +
    + {avatarDom} + {MetaDetail} +
    + ); + }; }, }); diff --git a/components/card/__tests__/__snapshots__/demo.test.js.snap b/components/card/__tests__/__snapshots__/demo.test.js.snap index 4e2733b3a..4cc8d52c0 100644 --- a/components/card/__tests__/__snapshots__/demo.test.js.snap +++ b/components/card/__tests__/__snapshots__/demo.test.js.snap @@ -294,35 +294,40 @@ exports[`renders ./components/card/demo/tabs.vue correctly 1`] = `
    Card title
    -
    -
    -
    -
    -
    -
    -
    - - -
    -
    -
    +
    +
    + +
    +
    +
    + +
    +
    + + +
    + +
    +
    +
    +
    + + +
    + + +
    +
    +
    +
    + +
    +
    -
    -
    -
    -
    -
    -
    - -
    -
    @@ -335,42 +340,47 @@ exports[`renders ./components/card/demo/tabs.vue correctly 1`] = `
    -
    -
    - -
    -
    -
    -
    -
    - - - -
    -
    -
    +
    +
    + +
    +
    +
    + +
    +
    + + +
    +
    + + +
    + +
    +
    +
    +
    + + +
    + + +
    +
    +
    + +
    + +
    +
    -
    -
    - -
    -
    -
    -
    - -
    -
    diff --git a/components/card/__tests__/__snapshots__/index.test.js.snap b/components/card/__tests__/__snapshots__/index.test.js.snap index bf48381bf..5c0c2a300 100644 --- a/components/card/__tests__/__snapshots__/index.test.js.snap +++ b/components/card/__tests__/__snapshots__/index.test.js.snap @@ -5,7 +5,7 @@ exports[`Card should still have padding when card which set padding to 0 is load
    -
    +
    diff --git a/components/card/demo/tabs.vue b/components/card/demo/tabs.vue index 890fd69d2..5be91cd8b 100644 --- a/components/card/demo/tabs.vue +++ b/components/card/demo/tabs.vue @@ -24,8 +24,8 @@ More content can be hosted :active-tab-key="key" @tabChange="key => onTabChange(key, 'key')" > -