Tab 选项卡
如果项目中使用的是 1.x 版本的基础组件(@alifd/next),请在左侧导航顶部切换组件版本。
安装方法
- 在命令行中执行以下命令
npm install @icedesign/base@latest -S
Guide
TAB 让用户可以在不同子任务、视图、模式之间切换,它具有全局导航的作用,是全局功能的主要展示和切换区域,一个TAB标记一个核心功能,TAB之间可以快速点击切换。该窗口包含2个以上的选项卡,所有选项卡可以排列在一行中,即使该用户界面被本地化后也是如此。提供平级的区域将大块内容进行收纳和展现,保持界面整洁。
何时使用
Fusion 提供了三级选项卡,分别用于不同的场景。
普通选项卡,引领整页面的内容,起导航的作用。
文本型选项卡。
包裹型选项卡,在页面结构中,只是局部展示,需要和其他内容结合出现。
胶囊型选项卡。
关于动效
如果您不想开启动效,可以通过设置 animation
属性值为 false
来关闭。
注意事项
对于 0.x
版本的 Tab 组件而言,在实现上使用了 key
作为内部标识字段,如果用户使用了 React 官方提供的类似于 React.Children.toArray
等子元素遍历方法时,会导致原始的 key
值被修改,这一行为会导致部分逻辑出错(判断当前激活的 TabPane)。为了保证兼容性,我们将会在 1.x
版本进行变更。如果你需要用到 React.Children.toArray
方法,可以使用 @alife/next-util
中提供的 children.toArray
方法。
API
选项卡
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
prefix | 样式前缀 | String | 'next-' |
activeKey | 被激活的选项卡的 key(受控) | Number/String | - |
defaultActiveKey | 初始化时被激活的选项卡的 key(非受控) | Number/String | - |
type | 类型可选值:'bar', 'wrapped', 'text', 'capsule' | Enum | 'bar' |
animation | 是否开启动效 | Boolean | true |
resDirection | 多余项的展现方向可选值:'horizontal', 'vertical' | Enum | 'horizontal' |
tabPosition | 导航选项卡的位置,只适用于包裹型(wrapped)选项卡可选值:'top', 'bottom', 'left', 'right' | Enum | 'top' |
size | 尺寸可选值:'small', 'medium' | Enum | 'medium' |
closeable | 是否可关闭选项卡,只支持 bar 和 wrapped 两种类型 | Boolean | false |
triggerType | 触发选项卡的方式可选值:'hover', 'click' | Enum | 'click' |
lazyLoad | 是否提前渲染好所有 TabPane 的内容 | Boolean | true |
navStyle | 导航条的附加样式 | Object | {} |
contentStyle | 内容区的附加样式 | Object | {} |
tabBarExtraContent | 导航栏附加内容 | ReactNode | null |
onChange | 选项卡发生切换时的事件回调签名:Function(key: String) => void参数:key: {String} 改变后的 key | Function | () => {} |
onClose | 选项卡被关闭时的事件回调签名:Function(key: String, event: Object) => void参数:key: {String} 关闭的选项卡的 keyevent: {Object} Event 对象 | Function | () => {} |
Tab.TabPane
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
tab | 选项卡标题 | any | - |
closeable | 单个选项卡是否可关闭 | Boolean | true |
tabStyle | 单个选项卡的补充样式 | Object | - |
tabClassName | 单个选项卡的附加样式类 | String | - |
onClick | 点击单个选项卡时触发的回调签名:Function(key: String) => void参数:key: {String} 选项卡的 key | Function | () => {} |
onMouseEnter | 鼠标进入时触发的回调签名:Function(key: String) => void参数:key: {String} 选项卡的 key | Function | () => {} |
onMouseLeave | 鼠标离开时出发的回调签名:Function(key: String) => void参数:key: {String} 选项卡的 key | Function | () => {} |
代码示例
请务必给每个 TabPane 传入一个 key
值作为每个 TabPane 的唯一标识字段。创建一个基本的选项卡,其默认类型为bar
,并默认选中第一项。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const tabs = [
{ tab: "首页", key: "home", content: "这里是首页内容" },
{ tab: "文档", key: "doc", content: "这里是文档内容" },
{ tab: "API", key: "api", content: "这里是 API 内容" }
];
function handleChange(key) {
console.log("change", key);
}
function handleClick(key) {
console.log("click", key);
}
ReactDOM.render(
<Tab onChange={handleChange}>
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab} onClick={handleClick}>
{item.content}
</TabPane>
))}
</Tab>,
mountNode
);
此外用户还可以单独在单个 TabPane
上设置是否可关闭的属性。可关闭选项卡,可以通过控制 closable
属性设置选项卡是否可关闭。处于视觉上的考虑,目前该属性只支持包裹型选项卡(wrapped
)和普通选项卡(bar
)。
查看源码在线预览
import { Tab, Button, Icon } from "@icedesign/base";
const TabPane = Tab.TabPane;
const panes = [
{ tab: "邮件", key: 1, closeable: false },
{ tab: "消息通知", key: 2 },
{ tab: "设置", key: 3 },
{ tab: "未读邮件", key: 4 }
];
class CloseableTab extends React.Component {
constructor(props) {
super(props);
this.state = {
panes: panes,
activeKey: panes[0].key
};
}
/*eslint-disable eqeqeq */
remove(targetKey) {
let activeKey = this.state.activeKey;
let lastIndex;
this.state.panes.forEach((item, i) => {
if (item.key == targetKey) {
lastIndex = i - 1;
}
});
const panes = this.state.panes.filter(pane => pane.key != targetKey);
if (lastIndex >= 0 && activeKey == targetKey) {
activeKey = panes[lastIndex].key;
}
this.setState({ panes, activeKey });
}
onClose(targetKey) {
this.remove(targetKey);
}
onChange(activeKey) {
this.setState({ activeKey });
}
addTabpane() {
this.setState(prevState => {
const { panes } = prevState;
panes.push({ tab: "new tab", key: Math.random() });
return { panes };
});
}
render() {
const state = this.state;
return (
<div>
<Button onClick={::this.addTabpane}>
<Icon type="add" /> 新建选项卡
</Button>
<Tab
type="wrapped"
activeKey={state.activeKey}
closeable
onChange={::this.onChange}
onClose={::this.onClose}
className="custom-tab"
>
{state.panes.map(item => (
<TabPane tab={item.tab} key={item.key} closeable={item.closeable}>
{item.tab}的内容区域
</TabPane>
))}
</Tab>
</div>
);
}
}
ReactDOM.render(<CloseableTab />, mountNode);
.custom-tab {
margin-top: 14px;
}
此外,某些场合下,用户可能需要在某些特定的 tab
上添加样式,为此可以在 TabPane
上使用 tabClassName
和 tabStyle
来控制。如果需要定制导航条的样式,可以通过 navStyle
属性进行设置。如果需要定制内容区的样式,可以通过 contentStyle
属性进行设置。Tab 提供了丰富的属性让用户自定义组件的默认样式。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const panes = [
{
tab: "未处理任务",
key: 0
},
{
tab: "已处理任务",
key: 1
},
{
tab: "未处理消息",
key: 2
},
{
tab: "已处理消息",
key: 3
},
{
tab: "过期消息",
key: 4
}
];
const detachedContentStyle = {
borderLeft: 0,
borderRight: 0,
borderBottom: 0
};
ReactDOM.render(
<div className="fusion-demo">
<div className="demo-item-title">
通过 contentStyle 属性移除内容区默认边框
</div>
<Tab type="wrapped" contentStyle={detachedContentStyle}>
{panes.map(pane => (
<TabPane tab={pane.tab} key={pane.key}>
{pane.tab}
</TabPane>
))}
</Tab>
<div className="demo-item-title">
搭配使用 contentStyle, navStyle, tabClassName, tabStyle 等自定义样式属性
</div>
<Tab
type="wrapped"
contentStyle={{ padding: 0 }}
navStyle={{ background: "#FFF0E6" }}
>
{panes.map(pane => {
return (
<TabPane
tab={pane.tab}
key={pane.key}
className="custom-content"
tabStyle={{ background: "#FFF" }}
tabClassName="custom-tabs-tab"
>
{pane.tab}
</TabPane>
);
})}
</Tab>
<div className="demo-item-title">利用 tabClassName 实现等宽导航</div>
<Tab type="capsule">
{panes.map(pane => (
<TabPane tab={pane.tab} key={pane.key} tabClassName="justify-tabs-tab">
{pane.tab}
</TabPane>
))}
</Tab>
</div>,
mountNode
);
.fusion-demo .demo-item-title {
font-size: 16px;
background: #eee;
color: #333;
padding: 8px;
margin: 14px 0;
text-align: center;
}
.custom-content {
color: #333;
padding: 15px;
}
.custom-tabs-tab {
margin-right: -1px !important;
}
.justify-tabs-tab {
width: 140px;
text-align: center;
}
除了使用简单文本作为选项卡的标题,用户还可以传入自定义组件作为标题。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const complexTab1 = (
<div className="custom-tab-wrapper">
<p className="tab-title">e-Checking</p>
<p className="tab-desc">Transaction fee: US $15</p>
</div>
);
const complexTab2 = (
<div className="custom-tab-wrapper">
<p className="tab-title">Bank Card</p>
<p className="tab-desc">Transaction fee: US $26</p>
</div>
);
const panes = [
{
tab: complexTab1,
key: 0
},
{
tab: complexTab2,
key: 1
}
];
function callback(key) {
console.log(key);
}
ReactDOM.render(
<Tab onChange={callback} type="wrapped">
{panes.map(pane => (
<TabPane tab={pane.tab} key={pane.key} tabStyle={{ height: "60px" }}>
{pane.tab}
</TabPane>
))}
</Tab>,
mountNode
);
.custom-tab-wrapper {
line-height: 16px;
}
.tab-title {
margin: 10px 0 0 0;
font-size: 16px;
}
.tab-desc {
margin: 10px 0 0 0;
font-size: 12px;
}
可以通过 disabled
属性禁用某一个选型卡。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
ReactDOM.render(
<Tab>
<TabPane tab="选项卡一" key="1">
选项卡一
</TabPane>
<TabPane tab="选项卡二" disabled key="2">
选项卡二
</TabPane>
<TabPane tab="选项卡三" key="3">
选项卡三
</TabPane>
</Tab>,
mountNode
);
此时用户只要传入自定义组件给 TabPane 即可,Tab 可以将底层事件对象传递给用户的自定义组件。Tab 允许开发者在上层进行自由的行为控制,例如用户可以基于 Tab 开发一个标题部分双击可编辑的 Tab ,
查看源码在线预览
import { Tab, Input } from "@icedesign/base";
const TabPane = Tab.TabPane;
class EditableTabPane extends React.Component {
static propTypes = {
defaultTitle: React.PropTypes.string
};
constructor(props) {
super(props);
this.state = {
tabTitle: props.defaultTitle,
editable: false
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.defaultTitle !== this.state.tabTitle) {
this.setState({
tabTitle: nextProps.defaultTitle
});
}
}
onKeyDown(e) {
const { keyCode } = e;
// 由于 Tab 会监听键盘的 keyUp, keyDown, keyLeft, keyRight 四个按键用于支持键盘导航
// 如果上层需要使用到键盘事件,需要在这里停止事件冒泡
if (keyCode > 36 && keyCode < 41) {
e.stopPropagation();
}
}
onBlur(e) {
this.setState({
editable: false,
tabTitle: e.target.value
});
}
onDblClick() {
this.setState({
editable: true
});
}
render() {
const { tabTitle, editable } = this.state;
if (editable) {
return (
<Input
defaultValue={tabTitle}
onKeyDown={this.onKeyDown.bind(this)}
onBlur={this.onBlur.bind(this)}
/>
);
}
return <span onDoubleClick={this.onDblClick.bind(this)}>{tabTitle}</span>;
}
}
ReactDOM.render(
<Tab defaultActiveKey="1">
<TabPane tab={<EditableTabPane defaultTitle="选项卡一" />} key="1">
选项卡一
</TabPane>
<TabPane tab="选项卡二" key="2">
选项卡二
</TabPane>
</Tab>,
mountNode
);
可以通过设置 tabBarExtraContent
为 Tab 组件附加额外的内容,确保只在有限选项卡的情况下才使用附加内容。
查看源码在线预览
import { Tab, Button } from "@icedesign/base";
const TabPane = Tab.TabPane;
function handleChange(key) {
console.log(key);
}
function handleClick() {
console.log("hello world");
}
const extraContent = (
<Button type="primary" onClick={handleClick}>
Hello world
</Button>
);
ReactDOM.render(
<div className="fusion-demo">
<div className="demo-item-title">水平方向加 tabBarExtraContent</div>
<Tab
type="wrapped"
onChange={handleChange}
tabBarExtraContent={extraContent}
>
<TabPane tab="选项卡一" key="1">
选项卡一内容
</TabPane>
<TabPane tab="选项卡二" key="2">
选项卡二内容
</TabPane>
<TabPane tab="选项卡三" key="3">
选项卡三内容
</TabPane>
</Tab>
<div className="demo-item-title">垂直方向加 tabBarExtraContent</div>
<Tab
type="wrapped"
tabPosition="left"
onChange={handleChange}
tabBarExtraContent={extraContent}
>
<TabPane tab="选项卡一" key="1">
选项卡一内容
</TabPane>
<TabPane tab="选项卡二" key="2">
选项卡二内容
</TabPane>
<TabPane tab="选项卡三" key="3">
选项卡三内容
</TabPane>
</Tab>
</div>,
mountNode
);
.fusion-demo .demo-item-title {
font-size: 16px;
background: #eee;
color: #333;
padding: 8px;
margin: 14px 0;
text-align: center;
}
如果您需要在某些时候提前渲染好所有的 Content 内容,可以使用在 Tab 上关闭 lazyLoad
属性。默认情况 Tab 不会提前渲染好所有的内容,而是根据 Tab 的激活情况依次渲染。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const tabs = [
{ tab: "首页", key: 0, content: "这里是首页内容" },
{ tab: "文档", key: 1, content: "这里是文档内容" },
{ tab: "API", key: 2, content: "这里是 API 内容" }
];
ReactDOM.render(
<Tab lazyLoad={false}>
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab}>
{item.content}
</TabPane>
))}
</Tab>,
mountNode
);
可以将不同类型的选项卡进行嵌套
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
function callback(key) {
console.log(key);
}
ReactDOM.render(
<Tab onChange={callback} type="wrapped">
<TabPane tab="选项卡一" key="1">
<Tab type="wrapped">
<TabPane tab="1-1" key="11">
1-1
</TabPane>
<TabPane tab="1-2" key="12">
1-2
</TabPane>
<TabPane tab="1-3" key="13">
1-3
</TabPane>
</Tab>
</TabPane>
<TabPane tab="选项卡二" key="2">
<Tab type="bar">
<TabPane tab="2-1" key="21">
2-1
</TabPane>
<TabPane tab="2-2" key="22">
2-2
</TabPane>
<TabPane tab="3-3" key="23">
2-3
</TabPane>
</Tab>
</TabPane>
<TabPane tab="选项卡三" key="3">
<Tab type="capsule">
<TabPane tab="3-1" key="31">
3-1
</TabPane>
<TabPane tab="3-2" key="32">
3-2
</TabPane>
<TabPane tab="3-3" key="33">
3-3
</TabPane>
</Tab>
</TabPane>
<TabPane tab="选项卡三" key="4">
<Tab type="text">
<TabPane tab="4-1" key="41">
4-1
</TabPane>
<TabPane tab="4-2" key="42">
4-2
</TabPane>
<TabPane tab="4-3" key="43">
4-3
</TabPane>
</Tab>
</TabPane>
</Tab>,
mountNode
);
内容区的高度将会被自动附加一个 min-height
值,该值为导航条的高度。需要注意的是,当 tabPosition="left|right"
时,并且用户没有通过 contentStyle
属性自定义内容区的最小高度时,有四个位置,tabPosition="left|right|top|bottom"
。对于包裹型(type
值为 wrapped
)选项卡,支持通过 tabPosition
来指定选项卡标签的位置。
查看源码在线预览
import { Select, Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const contentStyle = {
background: "#FFF"
};
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
tabPosition: "bottom"
};
}
changeTabPosition(value) {
this.setState({ tabPosition: value });
}
render() {
return (
<div>
<Select
value={this.state.tabPosition}
onChange={::this.changeTabPosition}
className="tab-select-demo"
>
<div value="top">top</div>
<div value="bottom">bottom</div>
<div value="left">left</div>
<div value="right">right</div>
</Select>
<Tab
tabPosition={this.state.tabPosition}
type="wrapped"
contentStyle={contentStyle}
>
<TabPane tab="选项卡一" key="1">
选项卡一内容
</TabPane>
<TabPane tab="选项卡二" key="2">
选项卡二内容
</TabPane>
<TabPane tab="选项卡三" key="3">
选项卡三内容
</TabPane>
</Tab>
</div>
);
}
}
ReactDOM.render(<Demo />, mountNode);
.tab-select-demo {
margin-bottom: 20px;
}
small
尺寸的选项卡组件可以用在弹出框等较狭窄的容器内。组件尺寸,可以通过size
属性设置,提供medium
(默认)和small
两种尺寸,
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const tabs = [
{ tab: "首页", key: "home", content: "这里是首页内容" },
{ tab: "文档", key: "doc", content: "这里是文档内容" },
{ tab: "API", key: "api", content: "这里是 API 内容" }
];
ReactDOM.render(
<div>
<Tab size="small">
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab}>
{item.content}
</TabPane>
))}
</Tab>
<br />
<Tab size="small" type="wrapped">
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab}>
{item.content}
</TabPane>
))}
</Tab>
<br />
<Tab size="small" type="text">
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab}>
{item.content}
</TabPane>
))}
</Tab>
<br />
<Tab size="small" type="capsule">
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab}>
{item.content}
</TabPane>
))}
</Tab>
</div>,
mountNode
);
用户可以通过 resDirection
属性进行控制该行为。当容器无法容纳所有的选项卡标签时,Tab 组件支持选项卡左右滑动选择,或者下拉选择。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const tabs = [
{ tab: "选项卡一", key: 1 },
{ tab: "选项卡二", key: 2 },
{ tab: "选项卡三", key: 3 },
{ tab: "选项卡四", key: 4 },
{ tab: "选项卡五", key: 5 },
{ tab: "选项卡六", key: 6 },
{ tab: "选项卡七", key: 7 },
{ tab: "选项卡八", key: 8 },
{ tab: "选项卡九", key: 9 }
];
function onClick(key) {
console.log(key);
}
ReactDOM.render(
<div className="fusion-demo" style={{ width: "510px" }}>
<div className="demo-item-title">默认使用左右活动</div>
<Tab defaultActiveKey={1}>
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab} onClick={onClick}>
{item.tab}的内容。这里可以容纳更多内容。
</TabPane>
))}
</Tab>
<div className="demo-item-title">
resDirection = "vertical" 时使用下拉框容纳多余元素
</div>
<Tab defaultActiveKey={1} resDirection="vertical">
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab} onClick={onClick}>
{item.tab}的内容。这里可以容纳更多内容。
</TabPane>
))}
</Tab>
</div>,
mountNode
);
.fusion-demo .demo-item-title {
font-size: 16px;
background: #eee;
color: #333;
padding: 8px;
margin: 14px 0;
text-align: center;
}
值得注意的是,当使用 Grid 组件进行外层的布局时,由于 Gird 默认使用的是 flex
进行布局。因此,如果 Tab 组件拥有过多的选项卡时,会导致内层元素撑起整个 flex
容器。此时,需要给容器添加自定义样式 overflow: hidden
。
查看源码在线预览
import { Tab, Grid } from "@icedesign/base";
const { TabPane } = Tab;
const { Row, Col } = Grid;
const tabs = (function(length) {
const arr = [];
for (let i = 1; i < length; i++) {
arr.push({ tab: `tab ${i}`, key: i, content: `tab ${i} 的内容` });
}
return arr;
})(15);
function handleChange(key) {
console.log("change", key);
}
function handleClick(key) {
console.log("click", key);
}
ReactDOM.render(
<div className="custom-wrapper">
<Row className="custom-row">
<Col fixedSpan="12" className="custom-col-sidebar">
Sidebar
</Col>
<Col className="custom-col-content">
<Tab onChange={handleChange}>
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab} onClick={handleClick}>
{item.content}
</TabPane>
))}
</Tab>
</Col>
</Row>
</div>,
mountNode
);
.custom-row {
border: 1px solid #ccc;
}
.custom-col-sidebar {
border-right: 1px solid #ccc;
height: 130px;
line-height: 130px;
text-align: center;
}
.custom-col-content {
overflow: hidden;
}
Tab 支持 click
切换和 hover
切换两种触发类型,默认为 click
触发,您可以使用 triggerType
属性修改默认的触发类型。
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
const tabs = [
{ tab: "首页", key: 0, content: "这里是首页内容" },
{ tab: "文档", key: 1, content: "这里是文档内容" },
{ tab: "API", key: 2, content: "这里是 API 内容" }
];
function onChange(key) {
console.log("change", key);
}
function handleClick(key) {
console.log("click", key);
}
function onMouseEnter(key, e) {
console.log("enter", e.target, key);
}
function onMouseLeave(key, e) {
console.log("leave", e.target, key);
}
ReactDOM.render(
<div className="fusion-demo">
<div className="demo-item-title">triggerType = click</div>
<Tab triggerType="click" onChange={onChange}>
{tabs.map(item => (
<TabPane key={item.key} tab={item.tab} onClick={handleClick}>
{item.content}
</TabPane>
))}
</Tab>
<div className="demo-item-title">triggerType = hover</div>
<Tab triggerType="hover" onChange={onChange}>
{tabs.map(item => (
<TabPane
key={item.key}
tab={item.tab}
onClick={handleClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{item.content}
</TabPane>
))}
</Tab>
</div>,
mountNode
);
.fusion-demo .demo-item-title {
font-size: 16px;
background: #eee;
color: #333;
padding: 8px;
margin: 14px 0;
text-align: center;
}
capsule
胶囊型选项卡text
文本型选项卡wrapped
包裹型选项卡bar
普通选项卡(如不指定type
属性,则默认使用bar
型选项卡)根据使用场景及触发控件的类型,可以通过 type
属性配置选项卡的类型,主要包括:
查看源码在线预览
import { Tab } from "@icedesign/base";
const TabPane = Tab.TabPane;
function onChange(key) {
console.log(key);
}
const tabs = [
{ tab: "首页", key: "home", content: "这里是首页内容" },
{ tab: "文档", key: "doc", content: "这里是文档内容" },
{ tab: "API", key: "api", content: "这里是 API 内容" },
{ tab: "仓库", key: "repo", content: "这里是仓库内容" }
];
const types = ["bar", "wrapped", "text", "capsule"];
ReactDOM.render(
<div className="fusion-demo">
{types.map(type => (
<div key={type} className="fusion-demo-item">
<Tab type={type} onChange={onChange}>
{tabs.map(tab => (
<TabPane tab={tab.tab} key={tab.key}>
{tab.content}
</TabPane>
))}
</Tab>
</div>
))}
</div>,
mountNode
);
.fusion-demo-item {
margin: 14px 0;
}