A dead simple tab component for ReactJS.

Yarn or npm:

$ yarn add react-tabify

$ npm install --save react-tabify

import { Tab , Tabs } from ' react-tabify ' ; export default ( ) => ( < Tabs > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ;

react-tabify consists of two (2) components which need to be used together.

Name Type Default Description id string __tabify__ Id of the <Tabs /> component defaultActiveKey string / number 0 eventKey of the initial <Tab /> to render activeKey string / number eventKey of the current <Tab /> theme object Optional color theme stacked bool false Whether to display <Tabs /> vertically sticky bool false Enable sticky tabs onSelect func Callback fired when a <Tab /> is selected style object style forwarded to the <Tab /> containing <div /> children node <Tab /> components

Name Type Default Description eventKey string / number index Unique key of the <Tab /> label string / node Label of the <Tab/> hide bool false Whether to hide the <Tab/> style object style forwarded to the <Tab /> containing <div /> children node Any abritary React node

Uncontrolled Mode

By default, <Tabs /> are uncontrolled, and will display the first <Tab /> child during initial render. Use defaultActiveKey to default to another <Tab /> instead.

If <Tab /> components are not passed an eventKey , they will default to their order index. In the example below, we're defaulting <Tabs /> to display "Tab 3" since it sits at the second index ( defaultActiveKey={2} ).

export default ( ) => ( < Tabs defaultActiveKey = { 2 } > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ;

Controlled Mode

Alternatively, to control the component, pass an activeKey , however you must pass an onSelect callback to handle the event. onSelect passes the eventKey of the selected <Tab /> .

Again, if your <Tab /> components are not passed an eventKey , they will default to their order index.

import { Tab , Tabs } from ' react-tabify ' ; class App extends React . Component { constructor ( props ) { super ( props ) ; this . state = { activeKey : 0 } ; } handleTabSelect = activeKey => { this . setState ( { activeKey } ) ; } ; render ( ) { return ( < Tabs activeKey = { this . state . activeKey } onSelect = { this . handleTabSelect } > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ; } }

Add the stacked prop to render the tabs vertically.

export default ( ) => ( < Tabs stacked > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ;

If <Tabs /> is uncontrolled, pass sticky to "remember" the last active <Tab /> between page refreshes. When sticky is enabled, you must pass you own id to <Tabs /> . This will be used within LocalStorage to distinguish between multiple <Tabs /> instances.

LocalStorage must be enabled in the browser.

export default ( ) => ( < Tabs sticky > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ;

Easily nest tabs to create a section/subsection layout.

export default ( ) => ( < Tabs stacked > < Tab label = " Tab 1 " > < Tabs > < Tab label = " Subtab 1.1 " > Tab 1 Content 1 < / Tab > < Tab label = " Subtab 1.2 " > Tab 1 Content 2 < / Tab > < Tab label = " Subtab 1.3 " > Tab 1 Content 3 < / Tab > < / Tabs > < / Tab > < Tab label = " Tab 2 " > < Tabs > < Tab label = " Subtab 2.1 " > Tab 2 Content 1 < / Tab > < Tab label = " Subtab 2.2 " > Tab 2 Content 2 < / Tab > < Tab label = " Subtab 2.3 " > Tab 2 Content 3 < / Tab > < / Tabs > < / Tab > < Tab label = " Tab 3 " > < Tabs > < Tab label = " Subtab 3.1 " > Tab 3 Content 1 < / Tab > < Tab label = " Subtab 3.2 " > Tab 3 Content 2 < / Tab > < Tab label = " Subtab 3.3 " > Tab 3 Content 3 < / Tab > < / Tabs > < / Tab > < / Tabs > ) ;

To ensure that scrolling (i.e. overflow ) is only visible within the <Tab /> component, we'll want to wrap <Tabs /> with a Flexbox whose height is set to 100% . Otherwise, if our <Tab /> had enough content to induce a scrollbar, our entire <Tabs /> component would be subject to scrolling, which means the clickable tab links (horizontal and stacked) could scroll out of view.

const tabsContainer = { display : " flex " , height : " 100% " } ; const App = ( ) => ( < div style = { tabsContainer } > < Tabs stacked > < Tab label = " Tab 1 " style = { tabStyle } > { __getLorumIpsum ( ) } < / Tab > < Tab label = " Tab 2 " style = { tabStyle } > { __getLorumIpsum ( ) } < / Tab > < Tab label = " Tab 3 " style = { tabStyle } > { __getLorumIpsum ( ) } < / Tab > < / Tabs > < / div > ) ;

Use the hide prop to dynmically hide/show <Tab /> components. Pass a bool , or evaluate a function that returns a bool .

const __hasAccess = user => false ; const App = ( { user } ) => ( < div style = { styles } > < Tabs > < Tab label = " Super Admin Tab " hide > Super Admin Content < / Tab > < Tab label = " Admin Tab " hide = { ( ) => ! __hasAccess ( user ) } > Admin Content < / Tab > < Tab label = " User Tab " > User Content < / Tab > < / Tabs > < / div > ) ;

react-tabify leverages <ThemeManager /> from glamorous to expose an optional theme object. The tabs property of the theme controls the horizontal styling, while menu controls the stacked view.

Accepts any valid color (e.g. "red", "#FF0000", "hsl(0, 100%, 50%)", "rgb(255, 0, 0)", etc).

Theme object

const theme = { tabs : { color : < color > , borderBottomColor : < color > , active : { borderBottomColor : < color > , color : < color > } , hover : { borderBottomColor : < color > , color : < color > } } , menu : { color : < color > , borderRight : < color > , active : { backgroundColor : < color > , color : < color > } , hover : { color : < color > , backgroundColor : < color > } } } ;

Override any of the properties above. Here's a simple example:

const theme = { tabs : { color : " red " , active : { color : " green " } } } const App = ( ) => ( < Tabs theme = { theme } > < Tab label = " Tab 1 " > First Content < / Tab > < Tab label = " Tab 2 " > Second Content < / Tab > < Tab label = " Tab 3 " > Third Content < / Tab > < / Tabs > ) ;

A more complex, yet very ugly example theme: