Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-dyn-tabs

Package Overview
Dependencies
Maintainers
0
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-dyn-tabs

React dynamic tabs with full API

  • 6.0.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
216
decreased by-31.65%
Maintainers
0
Weekly downloads
 
Created
Source

Test coverage NPM version node React License npm download Build Status

react-dyn-tabs

React Dynamic Tabs with full API

Demo

Features

  • Responsive (using more button)
  • Full API (Open & Close & Select & Refresh & setOption & setTab, ...)
  • lazy loading and rendering
  • Customizable style
  • Return to last used tab when closing selected tab
  • PanelList can be rendered outside the TabList container
  • ARIA accessible
  • Customizable Tab component
  • Multiple themes
  • The core is about 23kb

Table of Contents

Installation

$ npm install react-dyn-tabs --save

or

$ yarn add react-dyn-tabs

If you need to directly include script in your html, use the following link :

<script src="https://unpkg.com/react-dyn-tabs@latest/dist/react-dyn-tabs.umd.min.js"></script>

Syntax

[TabList, PanelList, ready] = useDynTabs(initialOptions, plugins);

Minimal Usage Example

import React from 'react';
import 'react-dyn-tabs/style/react-dyn-tabs.css';
import 'react-dyn-tabs/themes/react-dyn-tabs-card.css';
import useDynTabs from 'react-dyn-tabs';

const initialOptions = {
  tabs: [
    {
      id: '1',
      title: 'tab 1',
      panelComponent: (porps) => <p> panel 1 </p>,
    },
    {
      id: '2',
      title: 'tab 2',
      panelComponent: (porps) => <p> panel 2 </p>,
    },
  ],
  selectedTabID: '1',
};

export default () => {
  const [TabList, PanelList] = useDynTabs(initialOptions);
  return (
    <div>
      <TabList></TabList>
      <PanelList></PanelList>
    </div>
  );
};

Simple Manipulation Example

import React from 'react';
import 'react-dyn-tabs/style/scss/react-dyn-tabs.scss';
import 'react-dyn-tabs/themes/scss/react-dyn-tabs-card.scss';
import useDynTabs from 'react-dyn-tabs';

const initialOptions = {
  tabs: [
    {
      id: '1',
      title: 'tab1',
      panelComponent: (porps) => <p> panel 1 </p>,
    },
    {
      id: '2',
      title: 'tab2',
      panelComponent: (porps) => <p> panel 2 </p>,
    },
  ],
  selectedTabID: '1',
};

export default () => {
  const [TabList, PanelList, ready] = useDynTabs(initialOptions);
  const addTab3 = function () {
    ready((instance) => {
      // open tab 3
      instance.open({id: '3', title: 'Tab 3', panelComponent: (porps) => <p> panel 3 </p>}).then(() => {
        console.log('tab 3 is open');
      });
      // switch to tab 3
      instance.select('3').then(() => {
        console.log('tab 3 is selected');
      });
    });
  };

  return (
    <div>
      <button onClick={addTab3}>Add tab 3</button>
      <TabList></TabList>
      <PanelList></PanelList>
    </div>
  );
};

NOTE :

  • Use ready function to access the instance object

    ready((instance) => {
      // manipulate tabs using instance object here
    });
    
  • ready function accepts a callback as its parameter and executes it as soon as Tabs get mounted.

  • If ready function is called after the Tabs has been mounted, the callback passed in will be executed immediately.

  • ready function can be executed multiple times and its identity is stable and won’t change on re-renders.

Options

tabs

typedefault valuerequireddescription

Array of tabData

[]falseinitial opened tabs

Example

const [TabList, PanelList, ready] = useDynTabs({
  tabs: [
    {
      id: '1',
      title: 'home',
      iconClass: 'fa fa-home',
      closable: true,
      panelComponent: (porps) => <p> home content </p>,
    },
    {
      id: '2',
      title: 'contact',
      tooltip: 'contact',
      disable: true,
      closable: false,
      panelComponent: (porps) => <p> contact content </p>,
    },
  ],
});

selectedTabID

typedefault valuerequireddescription
string' 'falsespecifies initial selected tab

Example

const [TabList, PanelList, ready] = useDynTabs({
  tabs: [
    {
      id: '1',
      title: 'home',
      iconClass: 'fa fa-home',
      closable: true,
      panelComponent: (porps) => <p> home content </p>,
    },
    {
      id: '2',
      title: 'contact',
      tooltip: 'contact',
      disable: true,
      closable: false,
      panelComponent: (porps) => <p> contact content </p>,
    },
  ],
  selectedTabID: '2',
});

direction

typedefault valuerequireddescription
string'ltr'falsecan be either of 'ltr' or 'rtl'

Example

const [TabList, PanelList, ready] = useDynTabs({direction: 'rtl'});

tabComponent

typerequireddescription
React componentfalsecustom tab component

Example

const [TabList, PanelList, ready] = useDynTabs({
  tabComponent: (props) => {
    const {id, isSelected, api: instance} = props;
    return (
      <button {...props.tabProps}>
        {props.children}
        {props.iconProps && <span {...props.iconProps}></span>}
      </button>
    );
  },
});

defaultPanelComponent

Default value for panelComponent option.

typerequireddescription
React component | React elementfalse

Example

const [TabList, PanelList, ready] = useDynTabs({
  defaultPanelComponent: (props) => {
    const {id, isSelected, api: instance} = props;
    return <div>loading...</div>;
  },
});

accessibility

typedefault valuerequireddescription
booleantruefalse

Example

const [TabList, PanelList, ready] = useDynTabs({accessibility: false});

NOTE :

When accessibility option is true, it sets the id attribute of panel and button elements.

isVertical

typedefault valuerequireddescription
booleanfalsefalse

Example

const [TabList, PanelList, ready] = useDynTabs({isVertical: true});

onLoad

typerequireddescription
functionfalseThis event is fired only once, when Tabs are mounted

Example

const [TabList, PanelList, ready] = useDynTabs({
  onLoad: function () {
    console.log('[onLoad]');
  },
});

NOTE :

You can use this keyword inside all callback options. It refers to the instance object.

onInit

typerequireddescription
functionfalseThis event is triggered after every render.

Example

const [TabList, PanelList, ready] = useDynTabs({
  onInit: function () {
    console.log('[onInit]');
  },
});

NOTE :

Do not use setState inside the onInit callback because it leads to an infinite loop.

onChange

typerequireddescription
functionfalsefires when we open|close|select a tab. this event is not fired initially

Example

const [TabList, PanelList, ready] = useDynTabs({
  onChange: function ({currentData, previousData, closedTabIDs, openedTabIDs}) {
    console.log('[onChange]');
  },
});

beforeSelect

typerequireddescription
functionfalse Fires when the user clicks on the tab, but before select them. This event should return boolean true or false, If the event returns false the tab is not selected.

Example

const [TabList, PanelList, ready] = useDynTabs({
  beforeSelect: function (e, id) {
    console.log('[beforeSelect]');
    return true;
  },
});

onFirstSelect

typerequireddescription
functionfalsefires after selecting a tab for the first time. It is not fired for the initial selected tab

Example

const [TabList, PanelList, ready] = useDynTabs({
  onFirstSelect: function ({currentSelectedTabId, previousSelectedTabId}) {
    console.log('[onFirstSelect]');
  },
});

onSelect

typerequireddescription
functionfalsefires after selecting a tab. this event is not fired for the initial selected tab

Example

const [TabList, PanelList, ready] = useDynTabs({
  onSelect: function ({currentSelectedTabId, previousSelectedTabId}) {
    console.log('[onSelect]');
  },
});

onOpen

typerequireddescription
functionfalsefires after opening tabs. this event is not fired for initial opened tabs

Example

const [TabList, PanelList, ready] = useDynTabs({
  onOpen: function (openedTabIDs) {
    console.log('[onOpen]');
  },
});

beforeClose

typerequireddescription
functionfalse fires when the user clicks on the close icon, but before close them. This event should return boolean true or false, If the event return false the tab is not closed.

Example

const [TabList, PanelList, ready] = useDynTabs({
  beforeClose: function (e, id) {
    console.log('[beforeClose]');
    return true;
  },
});

onClose

typerequireddescription
functionfalsefires after closing tabs

Example

const [TabList, PanelList, ready] = useDynTabs({
  onClose: function (closedTabIDs) {
    console.log('[onClose]');
  },
});

onDestroy

typerequireddescription
functionfalsefires before destroying useDynTabs hook

Example

const [TabList, PanelList, ready] = useDynTabs({
  onDestroy: function () {
    console.log('[onDestroy]');
  },
});

Instance methods

isOpen

Return value : boolean

Parameters:

  • id: String

Example

const result = instance.isOpen('Your tab ID');

open

Triggers onInit, onChange and onOpen events.

It only triggers onInit event, if the tab is already open.

Return value : Promise

Parameters:

  • tabData: Object

Example

if (instance.isOpen('contact') == false) {
  instance
    .open({
      id: 'contact',
      title: 'contact',
      tooltip: 'contact',
      disable: false,
      closable: true,
      iconClass: '',
      panelComponent: <ContactPanel></ContactPanel>,
    })
    .then(({currentData, instance}) => {
      console.log('contact tab is open');
    });
}

isSelected

Return value : boolean

Parameters:

  • id: String

Example

const result = instance.isSelected('Your tab ID');

select

Makes current and previous selected tab to be re-rendered

Triggers onInit, onChange and onSelect events.

It only triggers onInit event, if the tab is already selected.

Return value : Promise

Parameters:

  • id: string

Example

if (instance.isSelected('1') == false) {
  instance.select('1').then(({currentData, instance}) => {
    console.log('tab 1 is selected');
  });
}

close

Triggers onInit, onChange and onClose events.

It only triggers onInit event, if the tab is already closed.

When switching parameter is true, it switches to previous selected tab

Return value : Promise

Parameters:

  • id: string
  • switching: boolean (default : true)

Example

if (instance.isOpen('2') == true) {
  instance.close('2').then(({currentData, instance}) => {
    console.log('tab 2 is closed');
  });
}

refresh

Makes all tabs to be re-rendered.

triggers onInit event.

Return value : Promise

Example

instance.refresh().then(({currentData, instance}) => {});

getOption

Parameters:

  • optionName : String

Example

const direction = instance.getOption('direction');
const onSelect = instance.getOption('onSelect');

setOption

Can be used for setting all options except selectedTabID and tabs options.

This function does not re-render Tabs. If you need to re-render Tabs, use refresh method after this function.

Return value : instance object

Parameters:

  • optionName : String
  • optionValue : string|boolean|object|function

Example

instance.setOption('direction', 'rtl');
instance.setOption('onSelect', () => {});
instance.setOption('beforeSelect', () => false);

getTab

Get tabData object

Return value : tabData object

Parameters:

  • id : String

Example

const {id, title, tooltip, disable, lazy, iconClass, closable, panelComponent} = instance.getTab('contactID');
console.log(id); //contactID

setTab

Set tabData object.

This function does not re-render Tabs. If you need to re-render Tabs, use refresh method after this function.

Return value : instance object

Parameters:

  • tab id : String
  • source object : containing the properties you want to apply

Example

instance.setTab('home', {disable: true});
instance.setTab('contact', {closable: false, panelComponent: (props) => <p>contact panel</p>});

on

Attach an event handler function for one event.

Return value : instance object

Parameters:

  • event Name : String (can be either of onFirstSelect|onSelect|onClose|onOpen|onInit|onChange|onDestroy)
  • handler : function

Example

const handler = React.useCallback(function (params) {
  const {currentSelectedTabId, previousSelectedTabId} = params;
}, []);
instance.on('onSelect', handler);

one

Attach a handler to an event. The handler is executed at most once.

Return value : instance object

Parameters:

  • event Name : String (can be either of onFirstSelect|onSelect|onClose|onOpen|onInit|onChange|onDestroy)
  • handler : function

Example

instance.one('onSelect', function ({currentSelectedTabId, previousSelectedTabId}) {});

off

Remove an event handler.

Return value : instance object

Parameters:

  • event Name : String (can be either of onFirstSelect|onSelect|onClose|onOpen|onInit|onChange|onDestroy)
  • handler : function (A handler function previously attached for the event)

Example

const handler = React.useCallback(function () {}, []);
const attachHandler = () => {
  instance.on('onSelect', handler);
};
const deattachHandler = () => {
  instance.off('onSelect', handler);
};

getData

Get a copy of data

Return value : Data Object

Example

const {selectedTabID, openTabIDs} = instance.getData();

NOTE :

  • getCopyData function is an older version of getData function and it is enabled by default so that existing users do not have to change their code. You are free to use both conventions.

getPreviousData

Get a copy of data in previous render

Return value : Data Object

Example

const {selectedTabID, openTabIDs} = instance.getPreviousData();

NOTE :

  • getCopyPerviousData function is an older version of getPreviousData function and it is enabled by default so that existing users do not have to change their code. You are free to use both conventions.

sort

Useful for sorting Tabs manually.

Triggers onInit event.

Return value : Promise

Parameters:

  • Array of all Tabs IDs

Example

const {openTabIDs} = instance.getData();
instance.sort(openTabIDs.reverse()).then(({currentData, instance}) => {
  console.log('sorting Tabs has finished');
});

tabData

property nametypedefault valuerequireddescription
idstringfalsean unique identifier for each tab
titlestring' 'false
tooltipstring' 'false
panelComponentReact Element | React Component | nullA function component which returns empty divfalse
lazybooleanfalsefalse If set to false the panel will be rendered initially. if set to true the panel will not be rendered until the tab is activated
closablebooleantruefalse
iconClassstring' 'falseclass name for the icon
disablebooleanfalsefalse

Example

const tabData = {
  id: 'contactID',
  title: 'contactTitle',
  tooltip: 'contactTooltip',
  disable: true,
  lazy: true,
  iconClass: 'fa fa-home',
  closable: false,
  panelComponent: (porps) => <p> contact content </p>,
};
const [TabList, PanelList, ready] = useDynTabs({tabs: [tabData]});
// or
if (instance.isOpen(tabData.id) == false) {
  instance.open(tabData).then(() => {});
}

Lazy Loading

Defer loading of tab content until the tab is activated

Example 1

const Panel3 = React.lazy(() => import('./components/panel3.js'));
function LazyLoadingPanel3(porps) {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Panel3 {...porps}></Panel3>
    </Suspense>
  );
}
useDynTabs({
  tabs: [
    {id: '1', title: 'eager loading tab 1', panelComponent: <p>panel 1</p>},
    {id: '2', title: 'eager loading tab 2', lazy: true, panelComponent: <p>panel 2</p>},
    {id: '3', title: 'lazy loading tab 3', lazy: true, panelComponent: LazyLoadingPanel3},
  ],
  selectedTabID: '1',
});

NOTE :

  • panel 1 is eagerly loaded and rendered.
  • panel 2 is eagerly loaded but will not be rendered until tab 2 is activated.
  • panel 3 will not be loaded and rendered until tab 3 is activated.

Example 2 ( using onFirstSelect event )

useDynTabs({
  tabs: [
    {id: '1', title: 'eager loading tab 1', panelComponent: <p>panel 1</p>},
    {id: '2', title: 'eager loading tab 2', lazy: true, panelComponent: <p>panel 2</p>},
    {id: '3', title: 'lazy loading tab 3', lazy: true},
  ],
  selectedTabID: '1',
  defaultPanelComponent: function DefaultPanel() {
    return <div>loading...</div>;
  },
  onFirstSelect: function ({currentSelectedTabId}) {
    const instance = this;
    if (currentSelectedTabId === '3') {
      import('path to/panel3.js').then((defaultExportedModule) => {
        const Panel3 = defaultExportedModule.default;
        instance.setTab('3', {panelComponent: Panel3});
        instance.refresh();
      });
    }
  },
});

Plugins

More Button Plugin

Make Tabs responsive

Usage

import React from 'react';
import 'react-dyn-tabs/style/react-dyn-tabs.css';
import 'react-dyn-tabs/themes/react-dyn-tabs-card.css';
import useDynTabs from 'react-dyn-tabs';
import MoreButtonPlugin from 'react-dyn-tabs/plugins/moreButtonPlugin';

export default () => {
  const [TabList, PanelList, ready] = useDynTabs(initialOptions, [MoreButtonPlugin]);
  return (
    <div>
      <TabList></TabList>
      <PanelList></PanelList>
    </div>
  );
};

Options

option nametypedescription
moreButtonPlugin_buttonComponentReact Function Componentcustomize root component of more button
moreButtonPlugin_iconComponentReact Function Componentcustomize icon component of more button
moreButtonPlugin_buttonTooltipstring

Example

useDynamicTabs(
  {
    tabs: [
      {id: '1', title: 'tab1', panelComponent: <span>tab content 1</span>},
      {id: '2', title: 'tab2', panelComponent: <span>tab content 2</span>},
      {id: '3', title: 'tab3', panelComponent: <span>tab content 3</span>},
    ],
    selectedTabID: '1',
    moreButtonPlugin_iconComponent: ({instance}) => {
      return <i className={`fa fa-chevron-${instance.getOption('direction') === 'rtl' ? 'left' : 'right'}`} />;
    },
    moreButtonPlugin_buttonTooltip: 'show more tabs',
  },
  [MoreButtonPlugin],
);

Render custom components at the end of the Tablist

  • render new tab button example :

      const [TabList, PanelList, ready] = useDynTabs(initialOptions, [MoreButtonPlugin]);
      return (
        <div>
          <TabList>
            <button onClick={()=>{ ready(instance => instance.open({title:'new tab'})) }}>
              NEW
            </button>
          </TabList>
          <PanelList></PanelList>
        </div>
      );
    };
    
    
  • render close all button example :

      const [TabList, PanelList, ready] = useDynTabs(initialOptions, [MoreButtonPlugin]);
      return (
        <div>
          <TabList>
            <button onClick={()=>{ ready(instance=>{ instance.getData().openTabIDs.forEach(id=>instance.close(id,false)); })}}>
              CLOSE ALL
            </button>
          </TabList>
          <PanelList></PanelList>
        </div>
      );
    };
    
    

Styling

react-dyn-tabs does not include any style loading by default. Default stylesheets and themes are provided and can be included in your application if desired.

import 'react-dyn-tabs/style/react-dyn-tabs.min.css';
// or import 'react-dyn-tabs/style/scss/react-dyn-tabs.scss';
import 'react-dyn-tabs/themes/react-dyn-tabs-card.min.css';
// or import 'react-dyn-tabs/themes/scss/react-dyn-tabs-card.scss';

NOTE :

You can find other themes at themes folder and multiple themes example at example/multi-themes-example folder.

Include react-dyn-tabs/style/react-dyn-tabs-rtl.min.css for rtl mode

Caveats

  • Some actions like open, select, close and refresh cause re-rendering, and using them immediately after calling useDynTabs hook will create an infinite loop and other bugs that most likely you don't want to cause. you should use them inside event listeners or subscriptions.

  • Do not use setState inside the onInit callback because it leads to an infinite loop.

Test

$ npm run test

License

MIT

Keywords

FAQs

Package last updated on 14 Jul 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc