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

v6.2.1

Published

Create responsive and dynamic tabs in React. This library supports ARIA accessibility and provides complete control over tab management using hooks.

Downloads

1,121

Readme

react-dyn-tabs

Create responsive and dynamic tabs in React. This library supports ARIA accessibility and provides complete control over tab management using hooks.

Test coverage NPM version node React License npm download Build Status

Screenshot

Screenshot

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
  • RTL & Vertical Mode
  • 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'; // Mandatory CSS required by the react-dyn-tabs
import 'react-dyn-tabs/themes/react-dyn-tabs-card.css'; // Optional Theme applied to the react-dyn-tabs
import useDynTabs from 'react-dyn-tabs';

const initialOptions = {
  tabs: [
    {
      id: '1',
      title: 'tab 1',
      panelComponent: (props) => <p> panel 1 </p>,
    },
    {
      id: '2',
      title: 'tab 2',
      panelComponent: (props) => <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: (props) => <p> panel 1 </p>,
    },
    {
      id: '2',
      title: 'tab2',
      panelComponent: (props) => <p> panel 2 </p>,
    },
  ],
  selectedTabID: '1',
};

export default () => {
  const [TabList, PanelList, ready] = useDynTabs(initialOptions);

  const addTab3 = function () {
    // use ready function to access the instance object
    ready((instance) => {
      // open tab 3
      instance.open({id: '3', title: 'Tab 3', panelComponent: (props) => <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>
  );
};

ready function

The ready function in the react-dyn-tabs library is part of the array returned by the useDynTabs hook, alongside the TabList and PanelList components. This function allows developers to execute a callback when the TabList and PanelList components are fully mounted, providing access to the instance object for further manipulation.

Key Features

  • Multiple Calls: Developers can invoke the ready function multiple times without any issues.
  • Stable Identity: The reference to the ready function remains stable across component re-renders, ensuring consistent behavior.
  • Immediate Execution: If the ready function is called after the tabs have already been mounted, the provided callback will be executed immediately.

Example Usage

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

const addTab3 = function () {
  ready((instance) => {
    // open tab 3
    instance.open({id: '3', title: 'Tab 3', panelComponent: (props) => <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');
    });
  });
};

Options

tabs

Example

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

selectedTabID

Example

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

direction

Example

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

tabComponent

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.

Example

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

accessibility

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

Example

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

theme

Examples

  • in this exmaple, only bootstrap theme is applied to the Tablist, because value of theme option is bootstrap

    import 'react-dyn-tabs/themes/react-dyn-tabs-card.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-bootstrap.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-classic.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-basic.css';
    ...
    useDynTabs({theme:'bootstrap'});
  • in this exmaple, only classic theme is applied to the Tablist, because value of theme option is classic

    import 'react-dyn-tabs/themes/react-dyn-tabs-card.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-bootstrap.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-classic.css';
    import 'react-dyn-tabs/themes/react-dyn-tabs-basic.css';
    ...
    useDynTabs({theme:'classic'});

Notes

  • If the theme option is not provided then all imported themes CSS will be applied to the Tablist.

  • If the theme option is set to a empty string then imported themes CSS will not be applied to the Tablist.

  • You can create your own theme CSS and set the theme option to your theme class name

tablistStyle

Example

const [TabList, PanelList, ready] = useDynTabs({
  tablistStyle: {backgroundColor: 'blue'},
});

onLoad

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

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

Example

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

beforeSelect

Example

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

onFirstSelect

Example

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

onSelect

Example

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

onOpen

Example

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

beforeClose

Example

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

onClose

Example

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

onDestroy

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

Example

const tabData = {
  id: 'contactID',
  title: 'contactTitle',
  tooltip: 'contactTooltip',
  disable: true,
  lazy: true,
  iconClass: 'fa fa-home',
  closable: false,
  panelComponent: (props) => <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(props) {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Panel3 {...props}></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

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],
);

unpkg Link

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

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>
      );
    };
    

Themes And Style

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

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

For rtl mode you should also import following file

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

Themes

Themes define how the Tabs looks. The library comes with Provided Themes such as card and bootstrap. To use a theme you need to 1) import the themes CSS and 2) apply the chosen theme name to the theme option of the react-dyn-tabs.

  • card theme

    import 'react-dyn-tabs/themes/react-dyn-tabs-card.css';
    // or import 'react-dyn-tabs/themes/scss/react-dyn-tabs-card.scss';
    // or import 'react-dyn-tabs/themes/react-dyn-tabs-card.min.css';
    ...
    useDynTabs({theme:'card'});
  • bootstrap theme

    import 'react-dyn-tabs/themes/react-dyn-tabs-bootstrap.css';
    // or import 'react-dyn-tabs/themes/scss/react-dyn-tabs-bootstrap.scss';
    // or import 'react-dyn-tabs/themes/react-dyn-tabs-bootstrap.min.css';
    ...
    useDynTabs({theme:'bootstrap'});
  • basic theme

    import 'react-dyn-tabs/themes/react-dyn-tabs-basic.css';
    // or import 'react-dyn-tabs/themes/scss/react-dyn-tabs-basic.scss';
    // or import 'react-dyn-tabs/themes/react-dyn-tabs-basic.min.css';
    ...
    useDynTabs({theme:'basic'});
  • classic theme

    import 'react-dyn-tabs/themes/react-dyn-tabs-classic.css';
    // or import 'react-dyn-tabs/themes/scss/react-dyn-tabs-classic.scss';
    // or import 'react-dyn-tabs/themes/react-dyn-tabs-classic.min.css';
    ...
    useDynTabs({theme:'classic'});

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