docs: update tabs

pull/1845/head
tangjinzhou 2020-02-27 19:49:09 +08:00
parent 1d5e5b1f7d
commit e0975469bc
12 changed files with 116 additions and 56 deletions

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
dev: { dev: {
componentName: 'time-picker', // dev components componentName: 'tabs', // dev components
}, },
}; };

View File

@ -497,29 +497,65 @@ exports[`renders ./components/tabs/demo/slide.md correctly 1`] = `
<div class="ant-tabs-nav-scroll"> <div class="ant-tabs-nav-scroll">
<div class="ant-tabs-nav ant-tabs-nav-animated"> <div class="ant-tabs-nav ant-tabs-nav-animated">
<div> <div>
<div role="tab" aria-disabled="false" aria-selected="true" class="ant-tabs-tab-active ant-tabs-tab">Tab 1</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-1</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 2</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-2</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 3</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-3</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 4</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-4</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 5</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-5</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 6</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-6</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 7</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-7</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 8</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-8</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 9</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-9</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 10</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-10</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab 11</div> <div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-11</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-12</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-13</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-14</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-15</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-16</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-17</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-18</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-19</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-20</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-21</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-22</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-23</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-24</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-25</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-26</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-27</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-28</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-29</div>
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab">Tab-30</div>
</div> </div>
<div class="ant-tabs-ink-bar ant-tabs-ink-bar-animated" style="display: block; transform: translate3d(0px,0,0); webkit-transform: translate3d(0px,0,0); width: 0px;"></div> <div class="ant-tabs-ink-bar ant-tabs-ink-bar-animated" style="display: none;"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div tabindex="0" role="presentation" style="width: 0px; height: 0px; overflow: hidden; position: absolute;"></div> <div tabindex="0" role="presentation" style="width: 0px; height: 0px; overflow: hidden; position: absolute;"></div>
<div class="ant-tabs-content ant-tabs-content-animated ant-tabs-top-content" style="margin-left: 0%;"> <div class="ant-tabs-content ant-tabs-content-animated ant-tabs-top-content" style="display: none;">
<div role="tabpanel" aria-hidden="false" class="ant-tabs-tabpane ant-tabs-tabpane-active"> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div tabindex="0" role="presentation" style="width: 0px; height: 0px; overflow: hidden; position: absolute;"></div>Content of tab 1<div tabindex="0" role="presentation" style="width: 0px; height: 0px; overflow: hidden; position: absolute;"></div> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
</div> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>
<div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div> <div role="tabpanel" aria-hidden="true" class="ant-tabs-tabpane ant-tabs-tabpane-inactive"></div>

View File

@ -53,17 +53,19 @@ export default {
return ( return (
<div> <div>
<md cn={md.cn} us={md.us} /> <md cn={md.cn} us={md.us} />
<Basic /> <demo-sort>
<Disabled /> <Basic />
<Icon /> <Disabled />
<Slide /> <Icon />
<Extra /> <Slide />
<Size /> <Extra />
<Position /> <Size />
<Card /> <Position />
<EditableCard /> <Card />
<CardTop /> <EditableCard />
<CustomAddTrigger /> <CardTop />
<CustomAddTrigger />
</demo-sort>
<api> <api>
<template slot="cn"> <template slot="cn">
<CN /> <CN />

View File

@ -22,17 +22,7 @@ In order to fit in more tabs, they can slide left and right (or up and down).
@prevClick="callback" @prevClick="callback"
@nextClick="callback" @nextClick="callback"
> >
<a-tab-pane tab="Tab 1" key="1">Content of tab 1</a-tab-pane> <a-tab-pane v-for="i in 30" :tab="`Tab-${i}`" :key="i">Content of tab {{i}}</a-tab-pane>
<a-tab-pane tab="Tab 2" key="2">Content of tab 2</a-tab-pane>
<a-tab-pane tab="Tab 3" key="3">Content of tab 3</a-tab-pane>
<a-tab-pane tab="Tab 4" key="4">Content of tab 4</a-tab-pane>
<a-tab-pane tab="Tab 5" key="5">Content of tab 5</a-tab-pane>
<a-tab-pane tab="Tab 6" key="6">Content of tab 6</a-tab-pane>
<a-tab-pane tab="Tab 7" key="7">Content of tab 7</a-tab-pane>
<a-tab-pane tab="Tab 8" key="8">Content of tab 8</a-tab-pane>
<a-tab-pane tab="Tab 9" key="9">Content of tab 9</a-tab-pane>
<a-tab-pane tab="Tab 10" key="10">Content of tab 10</a-tab-pane>
<a-tab-pane tab="Tab 11" key="11">Content of tab 11</a-tab-pane>
</a-tabs> </a-tabs>
</div> </div>
</template> </template>

View File

@ -19,7 +19,7 @@ export const TimelineProps = {
pending: PropTypes.any, pending: PropTypes.any,
pendingDot: PropTypes.string, pendingDot: PropTypes.string,
reverse: PropTypes.bool, reverse: PropTypes.bool,
mode: PropTypes.oneOf(['left', 'alternate', 'right']), mode: PropTypes.oneOf(['left', 'alternate', 'right', '']),
}; };
export default { export default {

View File

@ -1,9 +1,16 @@
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { setTransform, isTransformSupported, getLeft, getTop, getActiveIndex } from './utils'; import {
setTransform,
isTransform3dSupported,
getLeft,
getStyle,
getTop,
getActiveIndex,
} from './utils';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
function componentDidUpdate(component, init) { function componentDidUpdate(component, init) {
const { styles = {}, panels, activeKey } = component.$props; const { styles = {}, panels, activeKey, direction } = component.$props;
const rootNode = component.getRef('root'); const rootNode = component.getRef('root');
const wrapNode = component.getRef('nav') || rootNode; const wrapNode = component.getRef('nav') || rootNode;
const inkBarNode = component.getRef('inkBar'); const inkBarNode = component.getRef('inkBar');
@ -17,7 +24,7 @@ function componentDidUpdate(component, init) {
} }
if (activeTab) { if (activeTab) {
const tabNode = activeTab; const tabNode = activeTab;
const transformSupported = isTransformSupported(inkBarNodeStyle); const transformSupported = isTransform3dSupported(inkBarNodeStyle);
// Reset current style // Reset current style
setTransform(inkBarNodeStyle, ''); setTransform(inkBarNodeStyle, '');
@ -42,6 +49,9 @@ function componentDidUpdate(component, init) {
left += (tabNode.offsetWidth - width) / 2; left += (tabNode.offsetWidth - width) / 2;
} }
} }
if (direction === 'rtl') {
left = getStyle(tabNode, 'margin-left') - left;
}
// use 3d gpu to optimize render // use 3d gpu to optimize render
if (transformSupported) { if (transformSupported) {
setTransform(inkBarNodeStyle, `translate3d(${left}px,0,0)`); setTransform(inkBarNodeStyle, `translate3d(${left}px,0,0)`);
@ -78,6 +88,7 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
direction: PropTypes.string,
prefixCls: String, prefixCls: String,
styles: Object, styles: Object,
tabBarPosition: String, tabBarPosition: String,

View File

@ -1,9 +1,9 @@
import addDOMEventListener from 'add-dom-event-listener';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import ResizeObserver from 'resize-observer-polyfill';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import BaseMixin from '../../_util/BaseMixin'; import BaseMixin from '../../_util/BaseMixin';
import { getComponentFromProp } from '../../_util/props-util'; import { getComponentFromProp } from '../../_util/props-util';
import { setTransform, isTransformSupported } from './utils'; import { setTransform, isTransform3dSupported } from './utils';
function noop() {} function noop() {}
export default { export default {
@ -19,6 +19,7 @@ export default {
navWrapper: PropTypes.func.def(arg => arg), navWrapper: PropTypes.func.def(arg => arg),
prevIcon: PropTypes.any, prevIcon: PropTypes.any,
nextIcon: PropTypes.any, nextIcon: PropTypes.any,
direction: PropTypes.string,
}, },
data() { data() {
@ -45,7 +46,8 @@ export default {
this.setNextPrev(); this.setNextPrev();
this.scrollToActiveTab(); this.scrollToActiveTab();
}, 200); }, 200);
this.resizeEvent = addDOMEventListener(window, 'resize', this.debouncedResize); this.resizeObserver = new ResizeObserver(this.debouncedResize);
this.resizeObserver.observe(this.$props.getRef('container'));
}); });
}, },
@ -57,8 +59,8 @@ export default {
}, },
beforeDestroy() { beforeDestroy() {
if (this.resizeEvent) { if (this.resizeObserver) {
this.resizeEvent.remove(); this.resizeObserver.remove();
} }
if (this.debouncedResize && this.debouncedResize.cancel) { if (this.debouncedResize && this.debouncedResize.cancel) {
this.debouncedResize.cancel(); this.debouncedResize.cancel();
@ -151,13 +153,13 @@ export default {
}, },
setOffset(offset, checkNextPrev = true) { setOffset(offset, checkNextPrev = true) {
const target = Math.min(0, offset); let target = Math.min(0, offset);
if (this.offset !== target) { if (this.offset !== target) {
this.offset = target; this.offset = target;
let navOffset = {}; let navOffset = {};
const tabBarPosition = this.$props.tabBarPosition; const tabBarPosition = this.$props.tabBarPosition;
const navStyle = this.$props.getRef('nav').style; const navStyle = this.$props.getRef('nav').style;
const transformSupported = isTransformSupported(navStyle); const transformSupported = isTransform3dSupported(navStyle);
if (tabBarPosition === 'left' || tabBarPosition === 'right') { if (tabBarPosition === 'left' || tabBarPosition === 'right') {
if (transformSupported) { if (transformSupported) {
navOffset = { navOffset = {
@ -170,6 +172,9 @@ export default {
}; };
} }
} else if (transformSupported) { } else if (transformSupported) {
if (this.$props.direction === 'rtl') {
target = -target;
}
navOffset = { navOffset = {
value: `translate3d(${target}px,0,0)`, value: `translate3d(${target}px,0,0)`,
}; };

View File

@ -17,6 +17,7 @@ export default {
getRef: PropTypes.func.def(noop), getRef: PropTypes.func.def(noop),
renderTabBarNode: PropTypes.func, renderTabBarNode: PropTypes.func,
tabBarPosition: PropTypes.string, tabBarPosition: PropTypes.string,
direction: PropTypes.string,
}, },
render() { render() {
const { const {
@ -26,6 +27,7 @@ export default {
tabBarGutter, tabBarGutter,
saveRef, saveRef,
tabBarPosition, tabBarPosition,
direction,
} = this.$props; } = this.$props;
const rst = []; const rst = [];
const renderTabBarNode = this.renderTabBarNode || this.$scopedSlots.renderTabBarNode; const renderTabBarNode = this.renderTabBarNode || this.$scopedSlots.renderTabBarNode;
@ -56,8 +58,9 @@ export default {
const tab = getComponentFromProp(child, 'tab'); const tab = getComponentFromProp(child, 'tab');
let gutter = tabBarGutter && index === children.length - 1 ? 0 : tabBarGutter; let gutter = tabBarGutter && index === children.length - 1 ? 0 : tabBarGutter;
gutter = typeof gutter === 'number' ? `${gutter}px` : gutter; gutter = typeof gutter === 'number' ? `${gutter}px` : gutter;
const marginProperty = direction === 'rtl' ? 'marginLeft' : 'marginRight';
const style = { const style = {
[isVertical(tabBarPosition) ? 'marginBottom' : 'marginRight']: gutter, [isVertical(tabBarPosition) ? 'marginBottom' : marginProperty]: gutter,
}; };
warning(tab !== undefined, 'There must be `tab` property or slot on children of Tabs.'); warning(tab !== undefined, 'There must be `tab` property or slot on children of Tabs.');
let node = ( let node = (

View File

@ -17,6 +17,8 @@ export default {
}, },
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
tabBarPosition: String, tabBarPosition: String,
direction: PropTypes.string,
destroyInactiveTabPane: PropTypes.bool,
}, },
computed: { computed: {
classes() { classes() {
@ -62,7 +64,7 @@ export default {
if (activeIndex !== -1) { if (activeIndex !== -1) {
const animatedStyle = animatedWithMargin const animatedStyle = animatedWithMargin
? getMarginStyle(activeIndex, tabBarPosition) ? getMarginStyle(activeIndex, tabBarPosition)
: getTransformPropValue(getTransformByIndex(activeIndex, tabBarPosition)); : getTransformPropValue(getTransformByIndex(activeIndex, tabBarPosition, direction));
style = animatedStyle; style = animatedStyle;
} else { } else {
style = { style = {

View File

@ -42,6 +42,7 @@ export default {
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
__propsSymbol__: PropTypes.any, __propsSymbol__: PropTypes.any,
direction: PropTypes.string.def('ltr'),
}, },
data() { data() {
const props = getOptionProps(this); const props = getOptionProps(this);
@ -177,6 +178,7 @@ export default {
raf.cancel(this.sentinelId); raf.cancel(this.sentinelId);
this.sentinelId = raf(() => { this.sentinelId = raf(() => {
if (this.destroy) return;
this.$forceUpdate(); this.$forceUpdate();
}); });
}, },
@ -190,10 +192,12 @@ export default {
renderTabContent, renderTabContent,
renderTabBar, renderTabBar,
destroyInactiveTabPane, destroyInactiveTabPane,
direction,
} = props; } = props;
const cls = { const cls = {
[prefixCls]: 1, [prefixCls]: 1,
[`${prefixCls}-${tabBarPosition}`]: 1, [`${prefixCls}-${tabBarPosition}`]: 1,
[`${prefixCls}-rtl`]: direction === 'rtl',
}; };
this.tabBar = renderTabBar(); this.tabBar = renderTabBar();
@ -204,6 +208,7 @@ export default {
tabBarPosition, tabBarPosition,
panels: props.children, panels: props.children,
activeKey: this.$data._activeKey, activeKey: this.$data._activeKey,
direction,
}, },
on: { on: {
keydown: this.onNavKeyDown, keydown: this.onNavKeyDown,
@ -217,6 +222,7 @@ export default {
tabBarPosition, tabBarPosition,
activeKey: this.$data._activeKey, activeKey: this.$data._activeKey,
destroyInactiveTabPane, destroyInactiveTabPane,
direction,
}, },
on: { on: {
change: this.setActiveKey, change: this.setActiveKey,

View File

@ -1,4 +1,4 @@
// based on rc-tabs 9.6.1 // based on rc-tabs 9.7.0
import ref from 'vue-ref'; import ref from 'vue-ref';
import Vue from 'vue'; import Vue from 'vue';
import Tabs from './Tabs'; import Tabs from './Tabs';

View File

@ -29,8 +29,10 @@ export function setTransform(style, v) {
style.mozTransform = v; style.mozTransform = v;
} }
export function isTransformSupported(style) { export function isTransform3dSupported(style) {
return 'transform' in style || 'webkitTransform' in style || 'MozTransform' in style; return (
('transform' in style || 'webkitTransform' in style || 'MozTransform' in style) && window.atob
);
} }
export function setTransition(style, v) { export function setTransition(style, v) {
@ -50,8 +52,11 @@ export function isVertical(tabBarPosition) {
return tabBarPosition === 'left' || tabBarPosition === 'right'; return tabBarPosition === 'left' || tabBarPosition === 'right';
} }
export function getTransformByIndex(index, tabBarPosition) { export function getTransformByIndex(index, tabBarPosition, direction = 'ltr') {
const translate = isVertical(tabBarPosition) ? 'translateY' : 'translateX'; const translate = isVertical(tabBarPosition) ? 'translateY' : 'translateX';
if (!isVertical(tabBarPosition) && direction === 'rtl') {
return `${translate}(${index * 100}%) translateZ(0)`;
}
return `${translate}(${-index * 100}%) translateZ(0)`; return `${translate}(${-index * 100}%) translateZ(0)`;
} }