{"id":13421901,"url":"https://github.com/ctxhou/react-tabtab","last_synced_at":"2025-07-20T02:12:48.428Z","repository":{"id":1592839,"uuid":"42986593","full_name":"ctxhou/react-tabtab","owner":"ctxhou","description":"💃 Make your react tab dance🕺","archived":false,"fork":false,"pushed_at":"2022-12-10T17:03:19.000Z","size":2042,"stargazers_count":413,"open_issues_count":45,"forks_count":55,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-07-18T04:40:25.114Z","etag":null,"topics":["drag","drop-tab","react","react-component","react-tab","react-tabtab","tab"],"latest_commit_sha":null,"homepage":"https://ctxhou.github.io/react-tabtab/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ctxhou.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-23T07:53:31.000Z","updated_at":"2025-07-03T15:33:45.000Z","dependencies_parsed_at":"2023-01-13T11:45:20.691Z","dependency_job_id":null,"html_url":"https://github.com/ctxhou/react-tabtab","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/ctxhou/react-tabtab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctxhou%2Freact-tabtab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctxhou%2Freact-tabtab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctxhou%2Freact-tabtab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctxhou%2Freact-tabtab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ctxhou","download_url":"https://codeload.github.com/ctxhou/react-tabtab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctxhou%2Freact-tabtab/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266057217,"owners_count":23870124,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drag","drop-tab","react","react-component","react-tab","react-tabtab","tab"],"created_at":"2024-07-30T23:00:33.634Z","updated_at":"2025-07-20T02:12:48.376Z","avatar_url":"https://github.com/ctxhou.png","language":"JavaScript","readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://i.imgur.com/6o66rig.png\" alt=\"\"\u003e\n  \u003cbr/\u003e\n  \u003cbr/\u003e\n\u003c/h1\u003e\n\n[![version](https://img.shields.io/npm/v/react-tabtab.svg)](https://www.npmjs.com/package/react-tabtab/)\n[![travis](https://travis-ci.org/ctxhou/react-tabtab.svg?branch=master)](https://travis-ci.org/ctxhou/react-tabtab)\n[![appveyor](https://ci.appveyor.com/api/projects/status/jn6724u4k4uer53j?svg=true)](https://ci.appveyor.com/project/ctxhou/react-tabtab)\n![david](https://david-dm.org/ctxhou/react-tabtab.svg)\n[![codecov](https://codecov.io/gh/ctxhou/react-tabtab/branch/master/graph/badge.svg)](https://codecov.io/gh/ctxhou/react-tabtab)\n![download](https://img.shields.io/npm/dm/react-tabtab.svg)\n![gzip size](http://img.badgesize.io/https://unpkg.com/react-tabtab/dist/react-tabtab.min.js?compression=gzip)\n\n\u003e A mobile support, draggable, editable and api based Tab for ReactJS. \u003cbr/\u003e\n\u003e *Support react \u003e= `v16.3`*\n\n**Note: Since v2, we don't support v15 and old styled-components version (\u003c4.0.0) [v15 document](https://github.com/ctxhou/react-tabtab/blob/v1.8.4/README.md)**\n\n### [Demo](https://ctxhou.github.io/react-tabtab/)\n\n![demo gif](https://media.giphy.com/media/xUOxeRdRrSvSLiX528/giphy.gif)\n\n## Features\n\n* **Mobile supported** — Touch support. Easy to use on mobile device\n* **Draggable tab** — Support drag and drop tab\n* **Add \u0026 Delete** — Tab can be added and deleted\n* **Async content** — Lazy load panel content\n* **Customizable style** — Based on `styled-components`, super easy to customize tab style\n* **API based** — All actions are controllable\n* **ARIA accessible**\n\n## Table of Contents\n\n\u003c!-- toc --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n  * [Minimal setup](#minimal-setup)\n  * [Draggable tab](#draggable-tab)\n  * [Async Panel](#async-panel)\n  * [Another Example](#another-example)\n- [Components / Api](#components--api)\n  * [\u0026lt;Tabs /\u0026gt;](#lttabs-gt)\n  * [\u0026lt;TabList /\u0026gt;](#lttablist-gt)\n  * [\u0026lt;Tab /\u0026gt;](#lttab-gt)\n  * [\u0026lt;DragTabList /\u0026gt;](#ltdragtablist-gt)\n  * [\u0026lt;DragTab/ \u0026gt;](#ltdragtab-gt)\n  * [\u0026lt;PanelList/ \u0026gt;](#ltpanellist-gt)\n  * [\u0026lt;Panel /\u0026gt;](#ltpanel-gt)\n  * [\u0026lt;AsyncPanel /\u0026gt;](#ltasyncpanel-gt)\n- [Customize style](#customize-style)\n  * [Use current style](#use-current-style)\n  * [Make your own style](#make-your-own-style)\n- [Development](#development)\n- [License](#license)\n\n\u003c!-- tocstop --\u003e\n\n## Installation\n\nInstall it with npm or yarn\n\nInstall `styled-components`. Because we put the `styled-components` to the peerDependencies, it suggests by [styled-components official blog](https://www.styled-components.com/docs/faqs#i-am-a-library-author-should-i-bundle-styledcomponents-with-my-library)\n\n```js\n$ npm install react-tabtab --save\n$ npm install styled-components@^4.0.0 --save\n```\n\nThen, import the module by module bundler like `webpack`, `browserify`\n\n```js\n// es6\nimport {Tabs, DragTabList, DragTab, PanelList, Panel, ExtraButton} from 'react-tabtab';\n\n// not using es6\nvar Tabtab = require('react-tabtab');\nvar Tabs = Tabtab.Tabs;\nvar DragTabList = Tabtab.DragTabList;\nvar DragTab = Tabtab.DragTab;\nvar PanelList = Tabtab.PanelList;\nvar Panel = Tabtab.Panel;\nvar ExtraButton = Tabtab.ExtraButton;\n```\n\nUMD build is also available. If you do this, you'll need to include the dependencies:\n\nFor example:\n\n```html\n\u003cscript src=\"https://unpkg.com/react@16.0.0/umd/react.production.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/react-dom@16.0.0/umd/react-dom.production.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/prop-types@15.6/prop-types.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/classnames@2.2.5/index.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/styled-components/dist/styled-components.min.js\" type=\"text/javascript\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/react-sortable-hoc/dist/umd/react-sortable-hoc.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/react-poppop/dist/react-poppop.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/react-tabtab/dist/react-tabtab.min.js\"\u003e\u003c/script\u003e\n```\n\nYou can reference [standalone.html](https://github.com/ctxhou/react-tabtab/blob/master/docs/standalone.html) example.\n\n\n## Usage\n\nReact-tabtab is a tab component with highly customization. You can create a tab in simply setting. You also can create a tab system full with `draggable`, `async loading`, `close and create button`.\nAll the actions are api based. It means there is `no state` in the component. Developers have full control.\n\n### Minimal setup\n\n```js\nimport React, {Component} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Tabs, TabList, Tab, PanelList, Panel} from 'react-tabtab';\n\nclass Basic extends Component {\n  render() {\n    return (\n      \u003cTabs\u003e\n        \u003cTabList\u003e\n          \u003cTab\u003eTab1\u003c/Tab\u003e\n          \u003cTab\u003eTab2\u003c/Tab\u003e\n        \u003c/TabList\u003e\n        \u003cPanelList\u003e\n          \u003cPanel\u003eContent1\u003c/Panel\u003e\n          \u003cPanel\u003eContent2\u003c/Panel\u003e\n        \u003c/PanelList\u003e\n      \u003c/Tabs\u003e\n    )\n  }\n}\n\nReactDOM.render(\u003cBasic/\u003e, document.getElementById('root'));\n```\n\nIt's simple to use. Zero configuration!\n\n### Draggable tab\n\n```js\nimport React, {Component} from 'react';\nimport {Tabs, DragTabList, DragTab, PanelList, Panel} from 'react-tabtab';\nimport {simpleSwitch} from 'react-tabtab/lib/helpers/move';\n\nexport default class Drag extends Component {\n  constructor(props) {\n    super(props);\n    this.handleTabChange = this.handleTabChange.bind(this);\n    this.handleTabSequenceChange = this.handleTabSequenceChange.bind(this);\n    this.state = {\n      activeIndex: 0,\n    }\n  }\n\n  handleTabChange(index) {\n    this.setState({activeIndex: index});\n  }\n\n  handleTabSequenceChange({oldIndex, newIndex}) {\n    const {tabs} = this.state;\n    const updateTabs = simpleSwitch(tabs, oldIndex, newIndex);\n    this.setState({tabs: updateTabs, activeIndex: newIndex});\n  }\n\n  render() {\n    const {activeIndex} = this.state;\n    return (\n      \u003cTabs activeIndex={activeIndex}\n            onTabChange={this.handleTabChange}\n            onTabSequenceChange={this.handleTabSequenceChange}\u003e\n        \u003cDragTabList\u003e\n          \u003cDragTab\u003eDragTab1\u003c/DragTab\u003e\n          \u003cDragTab\u003eDragTab2\u003c/DragTab\u003e\n        \u003c/DragTabList\u003e\n        \u003cPanelList\u003e\n          \u003cPanel\u003eContent1\u003c/Panel\u003e\n          \u003cPanel\u003eContent2\u003c/Panel\u003e\n        \u003c/PanelList\u003e\n      \u003c/Tabs\u003e\n    )\n  }\n}\nReactDOM.render(\u003cBasic/\u003e, document.getElementById('root'));\n```\n\nBased on above example, the different to implement `normal tab` or `drag tab` is using different wrapper and child.\n\nAnd all the actions are controllable. You can customize your switch action. But if you don't want to write customized switch logic, you can directly use `import {simpleSwitch} from 'react-tabtab/lib/helpers/move'` this built-in function.\n\n**normal tab**\n\n```js\n\u003cTabs\u003e\n  \u003cTabList\u003e\n    \u003cTab\u003eTab1\u003c/Tab\u003e\n  \u003c/TabList\u003e\n  \u003cPanelList\u003e\n    \u003cPanel\u003eContent1\u003c/Panel\u003e\n  \u003c/PanelList\u003e\n\u003c/Tabs\u003e\n```\n\n**drag tab**\n\n```js\n\u003cTabs\u003e\n  \u003cDragTabList\u003e\n    \u003cDragTab\u003eDragTab1\u003c/DragTab\u003e\n  \u003c/DragTabList\u003e\n  \u003cPanelList\u003e\n    \u003cPanel\u003eContent1\u003c/Panel\u003e\n  \u003c/PanelList\u003e\n\u003c/Tabs\u003e\n```\n\n### Async Panel\n\nIn some case, if the data is large or we want to save the bandwidth, lazy loading the content is possible solution. You can use `AsyncPanel` to laze load panel content.\nMoreover, you can mix lazy load panel with normal panel!\n\n```js\nimport React, {Component} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Tabs, TabList, Tab, PanelList, AsyncPanel, Panel} from 'react-tabtab';\n\nfunction loadContentFunc(callback) {\n  setTimeout(() =\u003e {\n    callback(null, [\n      {product: 'json'},\n      {product: 'joseph'}\n    ]);\n  }, 100);\n}\n\n// You also can provide promise as return function:\n// function loadContentFunc() {\n//   return fetch('/products')\n//     .then(resp =\u003e resp.json())\n//     .then(data =\u003e data);\n// }\n\nclass AsyncTab extends Component {\n  render() {\n    return (\n      \u003cTabs\u003e\n        \u003cTabList\u003e\n          \u003cTab\u003eTab1\u003c/Tab\u003e\n          \u003cTab\u003eTab2\u003c/Tab\u003e\n        \u003c/TabList\u003e\n        \u003cPanelList\u003e\n          \u003cPanel\u003eContent1\u003c/Panel\u003e\n          \u003cAsyncPanel loadContent={loadContentFunc}\n                      render={data =\u003e (\u003cdiv\u003e{JSON.stringify(data)}\u003c/div\u003e)}\n                      renderLoading={() =\u003e (\u003cdiv\u003eLoading...\u003c/div\u003e)}\n                      cache={true}\n          /\u003e\n        \u003c/PanelList\u003e\n      \u003c/Tabs\u003e\n    )\n  }\n}\n\nReactDOM.render(\u003cAsyncTab/\u003e, document.getElementById('root'));\n```\n\nTo implement lazy loading, use `AsyncPanel` to wrap your panel content. Remember to provide `loadContent`, `render`, `renderLoading` these 3 props.\n\nIn `loadContent` props, both `callback` and `promise` type are supported.\n\nIf you use `callback`, remember to call `callback` when finish async loading.\n\nIf you use `promise`, need to return promise action.\n\nWhen data is loading, the panel content will show `renderLoading` component.\n\nAfter finishing loading data, the panel content will show `render` component and react-tabtab will pass the `loadContent` result as first parameter. So you can customize the component of panel content.\n\nLive example: [Link](https://ctxhou.github.io/react-tabtab/#async)\n\n### Another Example\n\nExcept drag and drop tab, `react-tabtab` also support other usable application, like:\n\n* Add and close button: [Example](https://ctxhou.github.io/react-tabtab/#add-close)\n* Modal view at mobile support: [Example](https://ctxhou.github.io/react-tabtab/#modal)\n* Auto detect number of tab and make it scrollable\n* **All the action is controllable**:[Example](https://ctxhou.github.io/react-tabtab/#complicated)\n\nAll of these features are api based, so you can customize each action on demand.\n\nMore code examples are avalable [here](https://github.com/ctxhou/react-tabtab/blob/master/docs/components/).\n\n## Components / Api\n\n### \u0026lt;Tabs /\u0026gt;\n\n`\u003cTabs/\u003e` is the main component of `react-tabtab`. Most of the api is passed from it.\n\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003eprops\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003edefault\u003c/th\u003e\n      \u003cth\u003e\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003edefaultIndex\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eint\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003eset the \u003cb\u003einitial\u003c/b\u003e active key\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eactiveIndex\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eint\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003econtrol current activeIndex.\u003cbr/\u003eYou need to pass new activeIndex value if you want to show different tab.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003edefaultIndex\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eint\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003eset the \u003cb\u003einitial\u003c/b\u003e active key\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eshowModalButton\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003cbr/\u003e\u003ccode\u003enumber\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e4\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cul\u003e\n          \u003cli\u003e\u003cb\u003etrue\u003c/b\u003e: always show button\u003c/li\u003e\n          \u003cli\u003e\u003cb\u003efalse\u003c/b\u003e: always hide button\u003c/li\u003e\n          \u003cli\u003e\u003cb\u003e[number]\u003c/b\u003e: when \u003ccode\u003enumber of tab \u003e= [number]\u003c/code\u003e, show button\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eshowArrowButton\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eauto\u003c/code\u003e\u003cbr/\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003eauto\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cli\u003e\u003cb\u003eauto\u003c/b\u003e: detect tab width, if they exceed container, show button\u003c/li\u003e\n        \u003cli\u003e\u003cb\u003etrue\u003c/b\u003e: always show button\u003c/li\u003e\n        \u003cli\u003e\u003cb\u003efalse\u003c/b\u003e: always hide button\u003c/li\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eExtraButton\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eReact Node\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003e\n        customize extra button content, example: `+` button\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eonTabChange\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e() =\u003e tabIndex\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003e\n        return tabIndex is clicked\u003cbr/\u003e\n        You can use this api with \u003ccode\u003eactiveIndex\u003c/code\u003e. When user click tab, update \u003ccode\u003eactiveIndex\u003c/code\u003e.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eonTabSequenceChange\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e() =\u003e {oldIndex, newIndex}\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003e\n        return changed oldIndex and newIndex value\u003cbr/\u003e\n        With this api, you can do switch tab very easily.\n        \u003cb\u003eNote:\u003cb/\u003eThis api is only called by \u003ccode\u003e\u0026lt;DragTab/\u0026gt;\u003c/code\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eonTabEdit\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e() =\u003e {type: [delete], index}\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003e\n        When user click \u003cb\u003eclose button\u003c/b\u003e , this api will return the clicked close button index.\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ecustomStyle\u003c/td\u003e\n      \u003ctd\u003e\n        \u003cpre\u003e\n\u003ccode\u003e{\n  TabList: React.Element,\n  Tab: React.Element,\n  Panel: React.Element,\n  ActionButton: React.Element\n}\u003c/code\u003e\u003c/pre\u003e\n      \u003c/td\u003e\n      \u003ctd\u003eBootstrap theme\u003c/td\u003e\n      \u003ctd\u003e\n        customized tab style component\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n### \u0026lt;TabList /\u0026gt;\n\nUse to wrap `\u003cTab/\u003e`.\n\n### \u0026lt;Tab /\u0026gt;\n\nNormal Tab. Show the children component on tab.\n\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003eprops\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003edefault\u003c/th\u003e\n      \u003cth\u003e\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eclosable\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003efalse\u003c/td\u003e\n      \u003ctd\u003ewhether to show close button\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n**Example**\n\n```js\n\u003cTab\u003e\n  \u003ci className=\"fa fa-map-pin\"\u003e\u003c/i\u003e\n  map tab\n\u003c/Tab\u003e\n```\n\n### \u0026lt;DragTabList /\u0026gt;\n\nUse to wrap `\u003cDragTab/\u003e`.\n\n### \u0026lt;DragTab/ \u0026gt;\n\nA draggable tab. Api is the same with `\u003cTab/\u003e`\n\n### \u0026lt;PanelList/ \u0026gt;\n\nUse to wrap `\u003cPanel/\u003e`\n\n### \u0026lt;Panel /\u0026gt;\n\nTab content.\n\n### \u0026lt;AsyncPanel /\u0026gt;\n\nLazy loading panel content.\n\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003cth\u003eprops\u003c/th\u003e\n      \u003cth\u003etype\u003c/th\u003e\n      \u003cth\u003edefault\u003c/th\u003e\n      \u003cth\u003e\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eloadContent \u003cb\u003e*\u003c/b\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003ccode\u003e(cb) =\u003e cb(error, data)\u003c/code\u003e or \u003cbr/\u003e\n        \u003ccode\u003e(cb) =\u003e Promise\n      \u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003ewhen loadContent finish, call the callback or you can return promise\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003erender \u003cb\u003e*\u003c/b\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003ccode\u003e(data) =\u003e Component\u003c/code\u003e\n      \u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003ewhen finish loading data, render this component\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003erenderLoading \u003cb\u003e*\u003c/b\u003e\u003c/td\u003e\n      \u003ctd\u003e\n        \u003ccode\u003e() =\u003e Component\u003c/code\u003e\n      \u003c/td\u003e\n      \u003ctd\u003enull\u003c/td\u003e\n      \u003ctd\u003ewhen it is loading data, render this component\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ecache\u003c/td\u003e\n      \u003ctd\u003e\n        \u003ccode\u003eboolean\u003c/code\u003e\n      \u003c/td\u003e\n      \u003ctd\u003etrue\u003c/td\u003e\n      \u003ctd\u003eshould cache the data\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Customize style\n\n`react-tabtab` is based on `styled-components`. Therefore, it's super easy to customize the tab style.\n\nJust extend the default component style and pass it to `customStyle` props.\n\n### Use current style\n\nYou can check the current style at `src/themes` folder.\n\nFor example, if you want to use `material-design`, import the style and pass to `customStyle` props.\n\n**Example:**\n\n```js\nimport {Component} from 'react';\nimport {Tabs, TabList, Tab, PanelList, Panel} from 'react-tabtab';\nimport * as customStyle from 'react-tabtab/lib/themes/material-design';\n\nclass Customized extends Component {\n  render() {\n    return (\n      \u003cTabs customStyle={customStyle}\u003e\n        \u003cTabList\u003e\n          \u003cTab\u003eTab1\u003c/Tab\u003e\n          \u003cTab\u003eTab2\u003c/Tab\u003e\n        \u003c/TabList\u003e\n        \u003cPanelList\u003e\n          \u003cPanel\u003eContent1\u003c/Panel\u003e\n          \u003cPanel\u003eContent2\u003c/Panel\u003e\n        \u003c/PanelList\u003e\n      \u003c/Tabs\u003e\n    )\n  }\n}\n```\n\nAnd now your tab is material design style!\n\n### Make your own style\n\nIf current theme doesn't meet your demand, follow this three steps and create a new one.\n\n**First step: import current style**\n\n```js\nimport styled from 'styled-components';\nimport { styled as styledTabTab } from 'react-tabtab';\n\nlet {TabListStyle, ActionButtonStyle, TabStyle, PanelStyle} = styledTabTab;\n```\n\n**Second: extend style and export it**\n\n```js\nimport styled from 'styled-components';\nimport { styled as styledTabTab } from 'react-tabtab';\n\nlet {TabListStyle, ActionButtonStyle, TabStyle, PanelStyle} = styledTabTab;\n\nTabListStyle = styled(TabListStyle)`\n  // write css\n`;\n\nTabStyle = styled(TabStyle)`\n  // write css\n`;\n\nActionButtonStyle = styled(ActionButtonStyle)`\n  // write css\n`;\n\nPanelStyle = styled(PanelStyle)`\n  // write css\n`;\n\n// need to follow this object naming\nmodule.exports = {\n  TabList: TabListStyle,\n  ActionButton: ActionButtonStyle,\n  Tab: TabStyle,\n  Panel: PanelStyle\n}\n```\n\n**Last: import your style and use it!**\n\nWhen you finish the new `react-tabtab` style, feel free to add it to `theme/` folder and send PR!\n\n## Development\n\n```bash\n$ yarn\n$ npm start\n```\n## License\n\nMIT [@ctxhou](github.com/ctxhou)\n","funding_links":[],"categories":["UI Components","Demos","\u003csummary\u003eUI Components\u003c/summary\u003e"],"sub_categories":["Tabs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctxhou%2Freact-tabtab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fctxhou%2Freact-tabtab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctxhou%2Freact-tabtab/lists"}