An accessible and easy tab component for ReactJS.
Installations
npm install react-tabs
Developer
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
No
Node Version
18.16.1
NPM Version
9.5.1
Statistics
3,099 Stars
1,860 Commits
446 Forks
42 Watching
8 Branches
69 Contributors
Updated on 28 Nov 2024
Bundle Size
6.50 kB
Minified
2.40 kB
Minified + Gzipped
Languages
JavaScript (95.82%)
Less (1.41%)
SCSS (1.41%)
CSS (1.35%)
Total Downloads
Cumulative downloads
Total Downloads
140,161,800
Last day
-10.6%
150,998
Compared to previous day
Last week
0.6%
863,626
Compared to previous week
Last month
3.5%
3,770,997
Compared to previous month
Last year
30.5%
40,555,230
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
2
Peer Dependencies
1
Dev Dependencies
41
react-tabs
An accessible and easy tab component for ReactJS.
https://reactcommunity.org/react-tabs/
Version 5 or newer of
react-tabs
needs react version 18 or newerVersion 4 of
react-tabs
needs react version 16.8 or newer
react-tabs was tested on real mobile devices and browsers with
Installing
1yarn add react-tabs
or
1npm install --save react-tabs
Basic Example
1import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; 2import 'react-tabs/style/react-tabs.css'; 3 4export default () => ( 5 <Tabs> 6 <TabList> 7 <Tab>Title 1</Tab> 8 <Tab>Title 2</Tab> 9 </TabList> 10 11 <TabPanel> 12 <h2>Any content 1</h2> 13 </TabPanel> 14 <TabPanel> 15 <h2>Any content 2</h2> 16 </TabPanel> 17 </Tabs> 18);
API
Components
react-tabs consists of 4 components which all need to be used together.
<Tabs />
If you specify additional props on the <Tabs />
component they will be forwarded to the rendered <div />
.
className: string | Array<string> | { [string]: boolean }
default:
"react-tabs"
Provide a custom class name for the outer <div />
of the tabs.
You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of classnames on how to supply different class names.
defaultFocus: boolean
default:
false
If set to true
the tabs will be focused on initial render. This allows immediate use of keyboard keys to switch tabs after the first render.
defaultIndex: number
default:
0
This allows changing the tab that should be open on initial render. This is a zero-based index, so first tab is 0
, second tab is 1
, ...
This can only be used in uncontrolled mode when react-tabs handles the current selected tab internally and for this reason cannot be used together with
selectedIndex
. See here for more info on modes.
direction: string
default:
"ltr"
Provide the direction of the component, can be either rtl or ltr.
disabledTabClassName: string
default:
"react-tabs__tab--disabled"
Provide a custom class name for disabled tabs.
This option can also be set directly at the
<Tab />
component.
disableUpDownKeys: bool
default:
false
Disable up & down arrow keys to change tabs.
domRef: (node: ?HTMLElement) => void
default:
null
Register a callback that will receive the underlying DOM node for every mount. It will also receive null on unmount.
environment: Window
If you're rendering react-tabs
within a different window
context than the default one; for example, an iframe.
focusTabOnClick: boolean
default:
true
By default the tab that is clicked will also be focused in the DOM. If set to false
the tab will not be focused anymore.
Be aware that keyboard navigation will not work after click if set to false. Though one can still focus the tabs by pressing
tab
and then keyboard navigation will work.
forceRenderTabPanel: boolean
default:
false
By default only the current active tab will be rendered to DOM. If set to true
all tabs will be rendered to the DOM always.
This can also be enabled for each individual
<TabPanel />
component with its propforceRender
.
onSelect: (index: number, lastIndex: number, event: Event) => ?boolean
default:
undefined
This event handler is called every time a tab is about to change. It will be called with the index
that it will be changed to, the lastIndex
which was selected before and the underlying event
which is usually either a keydown
or click
event. When index
and lastIndex
are equal it means the user clicked on the currently active tab.
The callback can optionally return false
to cancel the change to the new tab.
Returning
false
when the change to the new tab should be canceled is also important in controlled mode, as react-tabs still internally handles the focus of the tabs.
In controlled mode the
onSelect
handler is a required prop.
selectedIndex: number
default:
null
Set the currently selected tab. This is a zero-based index, so first tab is 0
, second tab is 1
, ...
This enables controlled mode, which also requires onSelect
to be set. See here for more info on modes.
selectedTabClassName: string
default:
"react-tabs__tab--selected"
Provide a custom class name for the active tab.
This option can also be set directly at the
<Tab />
component.
selectedTabPanelClassName: string
default:
"react-tabs__tab-panel--selected"
Provide a custom class name for the active tab panel.
This option can also be set directly at the
<TabPanel />
component.
<TabList />
If you specify additional props on the <TabList />
component they will be forwarded to the rendered <ul />
.
className: string | Array<string> | { [string]: boolean }
default:
"react-tabs__tab-list"
Provide a custom class name for the <ul />
.
You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of classnames on how to supply different class names.
<Tab />
If you specify additional props on the <Tab />
component they will be forwarded to the rendered <li />
.
className: string | Array<string> | { [string]: boolean }
default:
"react-tabs__tab"
Provide a custom class name for the <li />
.
You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of classnames on how to supply different class names.
disabled: boolean
default:
false
Disable this tab which will make it not do anything when clicked. Also a disabled class name will be added (see disabledClassName
)
disabledClassName: string
default:
"react-tabs__tab--disabled"
Provide a custom class name for disabled tabs.
This option can also be set for all
<Tab />
components with the propdisabledTabClassName
on<Tabs />
.
selectedClassName: string
default:
"react-tabs__tab--selected"
Provide a custom class name for the active tab.
This option can also be set for all
<Tab />
components with the propselectedTabClassName
on<Tabs />
.
tabIndex: string
default: if selected
"0"
otherwisenull
Overrides the tabIndex to enabled tabbing between tabs.
<TabPanel />
If you specify additional props on the <TabPanel />
component they will be forwarded to the rendered <div />
.
className: string | Array<string> | { [string]: boolean }
default:
"react-tabs__tab-panel"
Provide a custom class name for the <div />
containing the tab content.
You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of classnames on how to supply different class names.
forceRender: boolean
default:
false
By default the tab content will only be rendered when the tab is active. If set to true
the tab will also be rendered if inactive.
This can also be enabled for all
<TabPanel />
components with the propforceRenderTabPanel
on<Tabs />
.
selectedClassName: string
default:
"react-tabs__tab-panel--selected"
Provide a custom class name for the active tab panel.
This option can also be set for all
<TabPanel />
components with the propselectedTabPanelClassName
on<Tabs />
.
Controlled vs Uncontrolled mode
React tabs has two different modes it can operate in, which change the way how much you need to take care about the state yourself.
Uncontrolled mode
This is the default mode of react-tabs and makes the react-tabs components handle its state internally. You can change the starting tab with defaultIndex
and you can listen for changes with onSelect
.
In this mode you cannot force a tab change during runtime.
1<Tabs defaultIndex={1} onSelect={(index) => console.log(index)}> 2 <TabList> 3 <Tab>Title 1</Tab> 4 <Tab>Title 2</Tab> 5 </TabList> 6 <TabPanel></TabPanel> 7 <TabPanel></TabPanel> 8</Tabs>
Controlled mode
This mode has to be enabled by supplying selectedIndex
to the <Tabs />
component.
In this mode react-tabs does not handle any tab selection state internally and leaves all the state management up to the outer application.
This mode also enforces you to set a handler for onSelect
. defaultIndex
does not have any effect and will therefore throw an error.
1const App = () => { 2 const [tabIndex, setTabIndex] = useState(0); 3 4 return ( 5 <Tabs selectedIndex={tabIndex} onSelect={(index) => setTabIndex(index)}> 6 <TabList> 7 <Tab>Title 1</Tab> 8 <Tab>Title 2</Tab> 9 </TabList> 10 <TabPanel></TabPanel> 11 <TabPanel></TabPanel> 12 </Tabs> 13 ); 14};
Styling
react-tabs does not include any style loading by default. Default stylesheets are provided and can be included in your application if desired.
Webpack
When using webpack and an appropriate loader (css-loader
, sass-loader
, less-loader
or style-loader
) you can simply import the default stylesheet.
1import 'react-tabs/style/react-tabs.css'; 2// or 3import 'react-tabs/style/react-tabs.scss'; 4// or 5import 'react-tabs/style/react-tabs.less';
SASS
When using SASS you can easily import the default styles
1@import '../../path/to/node_modules/react-tabs/style/react-tabs.scss';
LESS
When using LESS you can easily import the default styles
1@import '../../path/to/node_modules/react-tabs/style/react-tabs.less';
Custom Style
You can also always just simply copy the default style to your own css/scss/less and modify it to your own needs. The changelog will always tell you when classes change and we also consider changes that break the styling as semver major.
Custom Components
Set tabsRole
In case you want to create your own component wrapping the ones that the library provides, you have to set its tabsRole
. This value is used inside react-tabs to check the role of a component inside <Tabs />
.
Possible values for tabsRole are:
- Tab
- TabPanel
- TabList
- Tabs
Pass through properties
Note: Because of how react-tabs works internally (it uses cloning to opaquely control various parts of the tab state), you need to pass any incoming props to the component you're wrapping. The easiest way to do this is to use the rest and spread operators, e.g. see {...otherProps}
below.
1import { Tabs, TabList, Tab, TabPanel } from 'react-tabs'; 2import type { ReactTabsFunctionComponent, TabProps } from 'react-tabs'; 3 4// All custom elements should pass through other props 5const CustomTab: ReactTabsFunctionComponent<TabProps> = ({ 6 children, 7 ...otherProps 8}) => ( 9 <Tab {...otherProps}> 10 <h1>{children}</h1> 11 </Tab> 12); 13 14CustomTab.tabsRole = 'Tab'; // Required field to use your custom Tab 15 16const App = () => ( 17 <Tabs> 18 <TabList> 19 <CustomTab>Custom Tab 1</CustomTab> 20 <CustomTab>Custom Tab 2</CustomTab> 21 </TabList> 22 <TabPanel>Panel 1</TabPanel> 23 <TabPanel>Panel 2</TabPanel> 24 </Tabs> 25);
License
MIT
No vulnerabilities found.
Reason
30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
0 existing vulnerabilities detected
Reason
SAST tool detected but not run on all commits
Details
- Info: SAST configuration detected: CodeQL
- Warn: 1 commits out of 2 are checked with a SAST tool
Reason
Found 0/29 approved changesets -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:77: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:82: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:85: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/build.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/codeql-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/codeql-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/codeql-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/codeql-analysis.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/lock.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/lock.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ossar-analysis.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/ossar-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ossar-analysis.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/ossar-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ossar-analysis.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/ossar-analysis.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pkg-size-report.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/pkg-size-report.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/pkg-size-report.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/pkg-size-report.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pkg-size-report.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/pkg-size-report.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/pkg-size-report.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/pkg-size-report.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/website.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/website.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/website.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/website.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/website.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/website.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/website.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/reactjs/react-tabs/website.yml/main?enable=pin
- Info: 0 out of 19 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 10 third-party GitHubAction dependencies pinned
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: jobLevel 'contents' permission set to 'write': .github/workflows/website.yml:42
- Info: found token with 'none' permissions: .github/workflows/build.yml:1
- Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1
- Warn: no topLevel permission defined: .github/workflows/ossar-analysis.yml:1
- Info: found token with 'none' permissions: .github/workflows/website.yml:1
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Score
5.4
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More