npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-tabtab-next

v3.3.0

Published

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

Downloads

214

Readme

react-tabtab-next

license npm npm

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

(!) This lib based on react-tabtab but refactored using Typescript and replacing some deprecated libs

Demo Page

Demo Playground

for build a local playground run

npm run demo

also here Codesandbox playground

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

Install it with npm or yarn

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

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

// 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

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

export const Example = () => {
    return (
        <Tabs>
            <TabList>
                <Tab>Tab1</Tab>
                <Tab>Tab2</Tab>
            </TabList>
            <PanelList>
                <Panel>Content1</Panel>
                <Panel>Content2</Panel>
            </PanelList>
        </Tabs>
    );
};

It's simple to use. Zero configuration!

Draggable tab

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: <div>Content {i}</div>,
        });
    }
    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 key={index}>{tab.title}</Tab>);
            panelTemplate.push(<Panel key={index}>{tab.content}</Panel>);
        });
        return (
            <Tabs
                activeIndex={activeIndex}
                onTabChange={this.handleTabChange}
                onTabSequenceChange={this.handleTabSequenceChange}
                customStyle={this.props.customStyle}
            >
                <DragTabList>{tabsTemplate}</DragTabList>
                <PanelList>{panelTemplate}</PanelList>
            </Tabs>
        );
    }
}

ReactDOM.render(<Drag />, 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

<Tabs>
    <TabList>
        <Tab>Tab1</Tab>
        <Tab>Tab2</Tab>
    </TabList>
    <PanelList>
        <Panel>Content1</Panel>
        <Panel>Content2</Panel>
    </PanelList>
</Tabs>

Sortable tabs (+ ExtraButton)

<Tabs
    // customStyle={md}
    // activeIndex={activeTab}
    // onTabChange={handleOnTabChange}
    // onTabSequenceChange={handleOnTabSequenceChange}
    ExtraButton={
        <ExtraButton
            onClick={(e) => {
                console.log(e);
            }}
        >
            +
        </ExtraButton>
    }
>
    <DragTabList>
        <Tab>Tab1</Tab>
        <Tab>Tab2</Tab>
    </DragTabList>
    <PanelList>
        <Panel>Content1</Panel>
        <Panel>Content2</Panel>
    </PanelList>
</Tabs>

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!

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 (
        <Tabs>
            <TabList>
                <Tab>Tab1</Tab>
                <Tab>Tab2</Tab>
            </TabList>
            <PanelList>
                <Panel>Content1</Panel>
                <AsyncPanel
                    loadContent={loadContentFunc}
                    render={(data) => <div>{JSON.stringify(data)}</div>}
                    renderLoading={() => <div>Loading...</div>}
                    cache={true}
                />
            </PanelList>
        </Tabs>
    );
};

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.

Components / Api

<Tabs />

<Tabs/> is the main component of react-tabtab. Most of the api is passed from it.

<TabList />

Use to wrap <Tab/>.

<DragTabList />

Use to wrap <Tab/>.

<Tab />

Normal Tab. Show the children component on tab.

Example

<Tab>
    <i className="fa fa-map-pin"></i>
    map tab
</Tab>

<PanelList/ >

Use to wrap <Panel/>

<Panel />

Tab content.

<AsyncPanel />

Lazy loading panel content.

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

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:

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 (
            <Tabs customStyle={md}>
                <TabList>
                    <Tab>Tab1</Tab>
                    <Tab>Tab2</Tab>
                </TabList>
                <PanelList>
                    <Panel>Content1</Panel>
                    <Panel>Content2</Panel>
                </PanelList>
            </Tabs>
        );
    }
}

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

npm i
npm run demo

or

yarn install
yarn demo

Build the bundle

npm i

License

MIT