react-dyn-tabs v6.2.2
react-dyn-tabs
Create responsive and dynamic tabs in React. This library supports ARIA accessibility and provides complete control over tab management using hooks.
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
- ARIA accessible
- Customizable Tab component
- Multiple themes
- The core is about 23kb
Table of Contents
- Installation
- Syntax
- Minimal Usage Example
- Simple Manipulation Example
- ready function
- Options
- Instance methods
- tabData
- Lazy Loading
- Plugins
- Render custom components at the end of the Tablist
- Themes And Style
- Caveats
- Test
- License
Installation
$ npm install react-dyn-tabs --saveor
$ yarn add react-dyn-tabsIf 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
readyfunction multiple times without any issues. - Stable Identity: The reference to the
readyfunction remains stable across component re-renders, ensuring consistent behavior. - Immediate Execution: If the
readyfunction 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
bootstraptheme is applied to theTablist, because value ofthemeoption isbootstrapimport '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
classictheme is applied to theTablist, because value ofthemeoption isclassicimport '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
themeoption is not provided then all imported themes CSS will be applied to theTablist.If the
themeoption is set to a empty string then imported themes CSS will not be applied to theTablist.You can create your own theme CSS and set the
themeoption 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: stringswitching: 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 : StringoptionValue : 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); //contactIDsetTab
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 : Stringsource 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 :
getCopyDatafunction is an older version ofgetDatafunction 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 :
getCopyPerviousDatafunction is an older version ofgetPreviousDatafunction 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 tabbutton 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 allbutton 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 testLicense
MIT
1 year ago
1 year ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
