react-dyn-tabs
React Dynamic Tabs with full API
Features
- Based on React hook
- Open & Close & Select & Refresh
- lazy/eager loading
- Customizable style
- Full API
- Return to last used tab when closing selected tab
- PanelList can be rendered outside the TabList container
- ARIA accessible
- Supporting custom Tab component
- Batching updates
Table of Contents
Installation
$ npm install react-dyn-tabs --save
or
$ yarn add react-dyn-tabs
Basic Example
import React, {useEffect} from 'react';
import useDynTabs from 'react-dyn-tabs';
import 'react-dyn-tabs/style/react-dyn-tabs.css';
import 'react-dyn-tabs/themes/default.css';
import ContactComponent from './contact-component';
export default () => {
const options = {
tabs: [
{
id: '1',
title: 'home',
closable: false,
panelComponent: (porps) => <p> home content </p>,
},
{
id: '2',
title: 'contact',
panelComponent: ContactComponent,
},
],
selectedTabID: '1',
onLoad: function () {},
};
const [TabList, PanelList, ready] = useDynTabs(options);
useEffect(() => {
ready((instance) => {
instance.open({id: '3', title: 'Tab 3', panelComponent: (porps) => <p> Tab 3 content </p>});
instance.open({id: '4', title: 'Tab 4', panelComponent: (porps) => <p> Tab 4 content </p>});
instance.select('4');
});
}, []);
return (
<div>
<TabList></TabList>
<PanelList></PanelList>
</div>
);
};
ready function
-
ready function is returned by useDynTabs hook.
-
ready function accepts a function as a parameter and calls it with instance object after the first render, when the component is mounted.
-
Tabs can't be manipulated safely before the first render, use ready() to make a function available after the component is mounted.
-
ready function can be called multiple times
-
ready function and instance Object will not be changed after re-rendering multiple times.
-
When ready function is called after the first render, it calls its function parameter with instance object immediately.
Options
tabs
type | default value | required | description |
---|
Array of tabData
| [] | false | initial 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
type | default value | required | description |
---|
string | ' ' | false | initial selected tab id |
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
type | default value | required | description |
---|
string | 'ltr' | false | can be either of 'ltr' or 'rtl' |
Example
const [TabList, PanelList, ready] = useDynTabs({direction: 'rtl'});
or
if (instance.getOption('direction') !== 'ltr') {
instance.setOption('direction', 'ltr');
instance.refresh();
}
tabComponent
type | required | description |
---|
React component | false | custom 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>
);
},
});
or
const CustomTabComponent = (props) => {
const {id, isSelected, api: instance} = props;
return (
<button {...props.tabProps}>
{props.children}
{props.iconProps && <span {...props.iconProps}></span>}
</button>
);
};
instance.setOption('tabComponent', CustomTabComponent);
instance.refresh();
defaultPanelComponent
Default value for panelComponent option.
type | required | description |
---|
React component | React element | false | |
Example
const [TabList, PanelList, ready] = useDynTabs({
defaultPanelComponent: (props) => {
const {id, isSelected, api: instance} = props;
return <div></div>;
},
});
or
instance.setOption('defaultPanelComponent', (props) => <p></p>);
instance.refresh();
accessibility
type | default value | required | description |
---|
boolean | true | false | |
Example
const [TabList, PanelList, ready] = useDynTabs({accessibility: false});
or
if (instance.getOption('accessibility') == true) {
instance.setOption('accessibility', false).refresh();
}
NOTE :
This option assigns id attribute on panel element and button element inside the tab. for having elements without id attribute, set this option to false.
isVertical
type | default value | required | description |
---|
boolean | false | false | |
Example
const [TabList, PanelList, ready] = useDynTabs({isVertical: true});
onLoad
type | required | description |
---|
function | false | This event is fired only once, after first render |
Example
const [TabList, PanelList, ready] = useDynTabs({
onLoad: function () {
},
});
onInit
type | required | description |
---|
function | false | This event is triggered after every render. |
Example
const [TabList, PanelList, ready] = useDynTabs({
onInit: function () {
},
});
instance.setOption('onInit', () => {}).refresh();
instance.on('onInit', () => {});
onChange
type | required | description |
---|
function | false | fires 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}) {
},
});
instance.setOption('onChange', ({currentData, previousData, closedTabIDs, openedTabIDs}) => {}).refresh();
beforeSelect
type | required | description |
---|
function | false |
fires when the user clicks on the tab, but before select them.
This event should return boolean true or false, If the event return false the tab is not selected.
|
Example
const [TabList, PanelList, ready] = useDynTabs({
beforeSelect: function (e, id) {
return true;
},
});
instance
.setOption('beforeSelect', (e, id) => {
return true;
})
.refresh();
onSelect
type | required | description |
---|
function | false | fires after selecting tabs. this event is not fired initially |
Example
const [TabList, PanelList, ready] = useDynTabs({
onSelect: function ({currentSelectedTabId, previousSelectedTabId}) {
},
});
instance.setOption('onSelect', ({currentSelectedTabId, previousSelectedTabId}) => {}).refresh();
onOpen
type | required | description |
---|
function | false | fires after opening tabs. this event is not fired initially |
Example
const [TabList, PanelList, ready] = useDynTabs({
onOpen: function (openedTabIDs) {
},
});
instance.setOption('onOpen', (openedTabIDs) => {}).refresh();
beforeClose
type | required | description |
---|
function | false |
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) {
return true;
},
});
instance
.setOption('beforeClose', (e, id) => {
return true;
})
.refresh();
onClose
type | required | description |
---|
function | false | fires after closing tabs. this event is not fired initially |
Example
const [TabList, PanelList, ready] = useDynTabs({
onClose: function (closedTabIDs) {
},
});
instance.setOption('onClose', (closedTabIDs) => {}).refresh();
onDestroy
type | required | description |
---|
function | false | fires before destroying useDynTabs hook |
Example
const [TabList, PanelList, ready] = useDynTabs({
onDestroy: function () {
},
});
instance.setOption('onDestroy', () => {}).refresh();
Methods
isOpen
Return value : boolean
Parameters:
Example
const result = instance.isOpen('tab ID');
open
Triggers 'onInit', 'onChange' and 'onOpen' event. opening an already opened tab only triggers 'onInit' event.
Return value : Promise
Parameters:
Example
if (instance.isOpen('2') == false) {
instance
.open({
id: '2',
title: 'contact',
tooltip: 'contact',
disable: false,
closable: true,
iconClass: '',
panelComponent: <ContactPanel></ContactPanel>,
})
.then(({currentData, instance}) => {
});
}
isSelected
Return value : boolean
Parameters:
Example
const result = instance.isSelected('tab ID');
select
Makes current and previous selected tab to be re-rendered
Triggers 'onInit', 'onChange' and 'onSelect' event.
Selecting an already selected tab only triggers 'onInit' event.
Return value : Promise
Parameters:
Example
if (instance.isSelected('your tab id') == false) {
instance.select('your tab id').then(({currentData, instance}) => {
});
}
close
Triggers 'onInit', 'onChange' and 'onClose' event.
Closing an already closed tab only triggers 'onInit' event.
It switches to the previously selected tab before closing if switching parameter was true and tab was already opened and selected.
When the user clicks on the default close icon, close function is called with true value as a switching parameter.
Return value : Promise
Parameters:
id: string
switching: boolean (default : true)
Example
if (instance.isOpen('2') == true) {
instance.close('2').then(({currentData, instance}) => {
});
}
refresh
Makes all tabs to be re-rendered.
triggers onInit event.
Return value : Promise
Example
instance.refresh().then(({currentData, instance}) => {
});
getOption
Parameters:
Example
const direction = instance.getOption('direction');
const onSelect = instance.getOption('onSelect');
setOption
for re-rendering immediately after this function, you should call refresh method after it.
Return value : instance
Parameters:
optionName : String
optionValue : string|boolean|object|function
Example
instance.setOption('direction', 'rtl');
instance.setOption('onSelect', () => {});
getTab
get tabData by id
Return value : tabData object
Parameters:
Example
const tabData = instance.getTab('3');
console.log(tabData.id);
setTab
set tabData by id. for re-rendering immediately after this function, you should call refresh method after it.
Return value : instance
Parameters:
optionName : String
optionValue : string|boolean|object|function
Example
instance.setTab('disable', true);
instance.setTab('panelComponent', (props) => <p />);
on
Attach an event handler function for one event.
Return value : instance
Parameters:
event Name : String (can be either of onSelect|onClose|onOpen|onInit|onChange|onDestroy)
handler : function
Example
instance.on('onSelect', function (params) {
const {currentSelectedTabId, previousSelectedTabId} = params;
});
one
Attach a handler to an event. The handler is executed at most once.
Return value : instance
Parameters:
event Name : String (can be either of onSelect|onClose|onOpen|onInit|onChange|onDestroy)
handler : function
Example
instance.one('onSelect', function ({currentSelectedTabId, previousSelectedTabId}) {
});
off
Remove an event handler.
Return value : instance
Parameters:
event Name : String (can be either of onSelect|onClose|onOpen|onInit|onChange|onDestroy)
handler : function (A handler function previously attached for the event)
Example
const onSelectHandler = function (params) {
const {currentSelectedTabId, previousSelectedTabId} = params;
this.off('onSelect', onSelectHandler);
};
instance.on('onSelect', onSelectHandler);
getData
get a copy of data
Return value : 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 : 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.
tabData
property name | type | default value | required |
---|
id | string | | false |
title | string | ' ' | false |
tooltip | string | ' ' | false |
panelComponent | can be either of React Element or React Component | | false |
closable | boolean | true | false |
iconClass | string | ' ' | false |
disable | boolean | false | false |
Example
const tabData = {
id: 'contactID',
title: 'contactTitle',
tooltip: 'contactTooltip',
disable: true,
iconClass: 'fa fa-home',
closable: false,
panelComponent: (porps) => <p> contact content </p>,
};
const [TabList, PanelList, ready] = useDynTabs({tabs: [tabData]});
if (instance.isOpen(tabData.id) == false) {
instance.open(tabData).then(() => {});
}
Lazy Loading
upcoming...
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.css';
import 'react-dyn-tabs/themes/default.css';
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.
Deprecated features
These deprecated features can still be used, but should be used with caution because they are expected to be removed entirely sometime in the future. You should work to remove their use from your code.
- Third element of returned array by useDynTabs hook should not be used as an object, it is no longer recommended and only be kept for backwards compatibility purposes, may be removed in the future. Avoid using it as an object and use the code below instead of it.
const [TabList, PanelList, ready] = useDynTabs(options);
const open_tab_3 = function () {
ready(function (instance) {
if (instance.isOpen('3') === false) {
instance.open({id: '3', title: 'mock tab 3'});
instance.select('3');
}
});
};
-
First parameter of onSelect function is an object and has perviousSelectedTabId property which is deprecated. you should use previousSelectedTabId property instead of perviousSelectedTabId property.
-
First parameter of onChange function is an object and has perviousData property which is deprecated. you should use previousData property instead of perviousData property.
Test
$ npm run test
License
MIT