An open API service indexing awesome lists of open source software.

https://github.com/onmotion/react-tabtab-next

[TypeScript] A mobile support, draggable, editable and api based Tab for ReactJS
https://github.com/onmotion/react-tabtab-next

closable draggable react sortable tabs tabtab tabtab-next typescript

Last synced: 9 months ago
JSON representation

[TypeScript] A mobile support, draggable, editable and api based Tab for ReactJS

Awesome Lists containing this project

README

          

# react-tabtab-next

[![license](https://img.shields.io/github/license/onmotion/react-tabtab-next)](https://www.npmjs.com/package/@react-tabtab-next/tabtab)
[![npm](https://img.shields.io/npm/v/@react-tabtab-next/tabtab.svg)](https://www.npmjs.com/package/@react-tabtab-next/tabtab)
[![npm](https://img.shields.io/npm/dm/@react-tabtab-next/tabtab.svg?maxAge=43200&downloads)](https://www.npmjs.com/package/@react-tabtab-next/tabtab)

## A mobile support, draggable, editable and api based Tab for ReactJS

**(!) This lib based on [react-tabtab](https://github.com/ctxhou/react-tabtab) but refactored using Typescript and replacing some deprecated libs**

### [Demo Page](https://onmotion.github.io/react-tabtab-next/)

### [Demo Playground](https://codesandbox.io/s/react-tabtab-next-yk4moo)



for build a local playground run

```bash
npm run demo
```

also here Codesandbox [playground](https://codesandbox.io/s/react-tabtab-next-yk4moo)

## Features

- **Mobile supported** — Touch support. Easy to use on mobile device
- **Draggable tab** — Support drag and drop tab
- **Add & Delete** — Tab can be added and deleted
- **Async content** — Lazy load panel content
- **Customizable style** — Based on `styled-components`, super easy to customize tab style
- **API based** — All actions are controllable
- **ARIA accessible**

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)
- [Minimal setup](#minimal-setup)
- [Draggable tab](#draggable-tab)
- [Async Panel](#async-panel)
- [Another Examples](#another-examples)
- [Components / Api](#components--api)
- [Customize style](#customize-style)
- [Development](#development)
- [License](#license)

## Installation

Install it with npm or yarn

```sh
npm install @react-tabtab-next/tabtab --save
```

Then, import the module by module bundler like `webpack`, `browserify`

```js
// es6
import { Tabs, DragTabList, PanelList, Panel, ExtraButton } from '@react-tabtab-next/tabtab';

// not using es6
var Tabtab = require('react-tabtab');
var Tabs = Tabtab.Tabs;
```

## Usage

React-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`.
All the actions are api based. It means there is `no state` in the component. Developers have full control.

### Minimal setup

```js
import React from 'react';
import { Tabs, Panel, Tab, TabList, PanelList } from '@react-tabtab-next/tabtab';

export const Example = () => {
return (


Tab1
Tab2


Content1
Content2


);
};
```

It's simple to use. Zero configuration!

### Draggable tab

```js
import React, { Component } from 'react';
import { Tabs, DragTabList, PanelList, Panel, Tab, helpers } from '@react-tabtab-next/tabtab';

const makeData = (number, titlePrefix = 'Tab') => {
const data = [];
for (let i = 0; i < number; i++) {
data.push({
title: `${titlePrefix} ${i}`,
content:

Content {i}
,
});
}
return data;
};

export default class Drag extends Component {
constructor(props) {
super(props);
this.handleTabChange = this.handleTabChange.bind(this);
this.handleTabSequenceChange = this.handleTabSequenceChange.bind(this);
const tabs = makeData(10, 'Some Tab');
this.state = {
activeIndex: 0,
tabs,
};
}

handleTabChange(index) {
this.setState({ activeIndex: index });
}

handleTabSequenceChange({ oldIndex, newIndex }) {
const { tabs } = this.state;
const updateTabs = helpers.simpleSwitch(tabs, oldIndex, newIndex);
this.setState({ tabs: updateTabs, activeIndex: newIndex });
}

render() {
const { tabs, activeIndex } = this.state;
const tabsTemplate = [];
const panelTemplate = [];
tabs.forEach((tab, index) => {
tabsTemplate.push({tab.title});
panelTemplate.push({tab.content});
});
return (

{tabsTemplate}
{panelTemplate}

);
}
}

ReactDOM.render(, document.getElementById('root'));
```

Based on above example, the different to implement `normal tab` or `drag tab` is using different wrapper and child.

And 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.

### normal tab

```js


Tab1
Tab2


Content1
Content2

```

### Sortable tabs (+ ExtraButton)

```js
{
console.log(e);
}}
>
+

}
>

Tab1
Tab2


Content1
Content2

```

### Async Panel

In 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.
Moreover, you can mix lazy load panel with normal panel!

```js
import React from 'react';
import { Tabs, Panel, Tab, TabList, PanelList, AsyncPanel } from '@react-tabtab-next/tabtab';

const AsyncTabsExmple = () => {
const loadContentFunc = (callback) => {
setTimeout(() => {
callback(null, 'some content');
}, 1000);
};
return (


Tab1
Tab2


Content1

{JSON.stringify(data)}
}
renderLoading={() =>
Loading...
}
cache={true}
/>


);
};

export default AsyncTabsExmple;
```

To implement lazy loading, use `AsyncPanel` to wrap your panel content. Remember to provide `loadContent`, `render`, `renderLoading` these 3 props.

In `loadContent` props, both `callback` and `promise` type are supported.

If you use `callback`, remember to call `callback` when finish async loading.

If you use `promise`, need to return promise action.

When data is loading, the panel content will show `renderLoading` component.

After 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.

### Another Examples

More code examples are avalable [here](https://github.com/onmotion/react-tabtab-next/blob/master/demo/src/App.tsx).

## Components / Api

### <Tabs />

`` is the main component of `react-tabtab`. Most of the api is passed from it.



props
type
default



activeIndex
number
null
control current activeIndex.
You need to pass new activeIndex value if you want to show different tab.


defaultIndex
number
0
default selected index if active index is not provided


showModalButton
boolean
number
4



  • true: always show button


  • false: always hide button


  • [number]: when number of tab >= [number], show button





showArrowButton
auto
boolean
auto


  • auto: detect tab width, if they exceed container, show button


  • true: always show button


  • false: always hide button




  • ExtraButton
    React Node
    null

    customize extra button content, example: `+` button



    onTabChange
    (tabIndex) => {}
    null

    return tabIndex is clicked

    You can use this api with activeIndex. When user click tab, update activeIndex.



    onTabSequenceChange
    (oldIndex, newIndex) => {}
    null

    return changed oldIndex and newIndex value

    With this api, you can do switch tab very easily.
    Note:This api is only called by <DragTabList/>



    onTabClose
    (index) => {}
    null

    When user click close button , this api will return the clicked close button index.



    customStyle


    {
    TabList: React.Element,
    Tab: React.Element,
    Panel: React.Element,
    ActionButton: React.Element
    }


    theme

    customized tab style component


    ### <TabList />

    Use to wrap ``.

    ### <DragTabList />

    Use to wrap ``.

    ### <Tab />

    Normal Tab. Show the children component on tab.



    props
    type
    default



    closable
    boolean
    false
    whether to show close button

    **Example**

    ```js


    map tab

    ```

    ### <PanelList/ >

    Use to wrap ``

    ### <Panel />

    Tab content.

    ### <AsyncPanel />

    Lazy loading panel content.



    props
    type
    default



    loadContent *

    (cb) => cb(error, data) or

    (cb) => Promise

    null
    when loadContent finish, call the callback or you can return promise


    render *

    (data) => Component

    null
    when finish loading data, render this component


    renderLoading *

    () => Component

    null
    when it is loading data, render this component


    cache

    boolean

    true
    should cache the data

    ## Customize style

    `react-tabtab-next` is based on `styled-components`. Therefore, it's super easy to customize the tab style.

    Just extend the default component style and pass it to `customStyle` props.

    ### Use current style

    Install tabtab themes

    ```sh
    npm install @react-tabtab-next/themes --save
    ```

    Available themes: `md`, `bootstrap`, `bulma`

    For example, if you want to use `material-design`, import the style and pass to `customStyle` props.

    **Example:**

    ```js
    import React, { Component } from 'react';
    import { Tabs, TabList, Tab, PanelList, Panel } from '@react-tabtab-next/tabtab';
    import { md } from '@react-tabtab-next/themes';

    export default class Customized extends Component {
    render() {
    return (


    Tab1
    Tab2


    Content1
    Content2


    );
    }
    }
    ```

    And now your tab is material design style!

    ### Make your own style

    If current theme doesn't meet your demand, follow this three steps and create a new one.

    - First step: import current style

    ```js
    import styled from 'styled-components';
    import { styled as styledTabTab } from '@react-tabtab-next/tabtab';

    let { TabListStyle, ActionButtonStyle, TabStyle, PanelStyle } = styledTabTab;
    ```

    - Second: extend style and export it

    ```js
    import styled from 'styled-components';
    import { styled as themeStyled } from '@react-tabtab-next/tabtab';

    let { TabList, ActionButton, Tab, Panel } = themeStyled;

    TabList = styled(TabList)`
    background-color: transparent;
    line-height: 1.2;
    border: 0;
    `;

    Tab = styled(Tab)`
    padding: 1px 10px;
    position: relative;
    font-size: 12px;
    text-transform: uppercase;
    border: 0;
    background: transparent;
    ${(props) => {
    return props.active && !props.vertical
    ? `
    border-bottom: 2px solid #ce93d8;
    `
    : null;
    }}
    &:hover .tab-label_close-button {
    opacity: 1;
    }
    &:hover {
    color: unset;
    background: #89898920;
    }
    `;

    ActionButton = styled(ActionButton)`
    background-color: transparent;
    border-radius: 0;
    border: none;
    opacity: 0.3;
    transition: opacity 0.2s;
    & svg {
    font-size: 21px;
    padding: 0;
    }
    &:hover {
    opacity: 1;
    }
    `;

    Panel = styled(Panel)``;

    export { TabList, ActionButton, Tab, Panel };
    ```

    - Last: import your style and use it!

    When you finish the new `@react-tabtab-next/theme` style, feel free to add it to `theme/` folder and send PR!

    ## Development

    ```bash
    npm i
    npm run demo
    ```

    or

    ```bash
    yarn install
    yarn demo
    ```

    Build the bundle

    ```bash
    npm i
    ```

    ## License

    MIT