React NavTabs is a helper that integrates Material UI Tabs with React Router 4/5. The tabs then function as navigation and sync with the URL. Hyperlinks, Back/Forward buttons, and other navigation work as expected.
Motivation
I usually want each 'tab' in a set of tabs to have a unique URL. This makes Back/Forward function as users expect, and makes it possible to 'link' directly to any specific tabs.
Integrating Tabs with React Router requires making each 'tab' a <Link>
component, with a corresponding <Route>
component for each tab.
This requires a lot of boilerplate and is error-prone.
NavTabs makes it fast & easy to create navigation-tabs.
Try the demos at: https://allpro.github.io/react-nav-tabs
Play with the demo code at: https://codesandbox.io/s/github/allpro/react-nav-tabs/tree/master/example
If you pull or fork the repo, you can run the demos like this:
- In the root folder, run
npm start
- In a second terminal, in the
/example
folder, runnpm start
- The demo will start at http://localhost:3000
- Changes to the component or the demo will auto-update the browser
- NPM:
npm install @allpro/react-nav-tabs
- Yarn:
yarn add @allpro/react-nav-tabs
- CDN: Exposed global is
ReactNavTabs
- Unpkg:
<script src="https://unpkg.com/@allpro/react-nav-tabs/umd/react-nav-tabs.min.js"></script>
- JSDelivr:
<script src="https://cdn.jsdelivr.net/npm/@allpro/react-nav-tabs/umd/react-nav-tabs.min.js"></script>
- Unpkg:
NavTabs uses the new React Context API, so requires React 16.3.
It uses the withRouter()
HOC provided by React-Router 4+.
NavTabs will work in any project meeting these dependencies.
"peerDependencies": {
"prop-types": ">=15",
"react": ">=16.3",
"react-dom": ">=16.3",
"react-router-dom": ">=4"
}
NavTabs wraps Material UI <Tabs>
and <Tab>
components, plus
React Router <Route>
components. It generates all these components for you.
If you already use Material UI Tabs in your app,
it's very easy to convert them to NavTabs, with no change to their appearance.
NavTabs consists of 3 separate components:
-
<NavTabs>
Wrapper (default export)
Tab configuration is set on this component. It does not output any mark-up.
See NavTabs Component Props -
<Tabs>
Subcomponent (named export)
Outputs the Material UI<Tabs>
component.
See Tabs Subomponent Props -
<Content>
Subcomponent (named export)
Outputs the React Router<Route>
components (one per tab).
See Content Subomponent Props
The <Tabs>
and <Content>
are separate subcomponents so they can fit
inside any layout you need. NavTabs can also be nested (tabs within tabs).
Two internal helper component are also exported in case they are useful to devs:
-
<Placeholder>
Component (named export)
A simple placeholder component used when nocomponent
is specified.
Accepts atext
prop to customize the placeholder text.
Also accepts acode
prop, which is used by some NavTabs demos. -
<PropsRoute>
Component (named export)
A wrapper around the React Router<Route>
component. This allows props to be passed-through to the component specified for a route.
Use this in place of<Route>
if you want to pass-through props.
Any prop not applicable to a<Route>
is considered a component prop.
Usually you only need the tabs
prop.
The other props listed here are needed only for special cases.
-
tabs
{array}[null]
required
This is the configuration for all the tabs.
(Iftabs
is not set, a sample set of tabs will be displayed.)
Seetabs
Configuration below. -
defaultTab
{integer|false}[0]
optional
Specify which tab should display by default. (0 = first tab; 1 = second, etc.)
Set tofalse
to have no tab selected by default.
NavTabs will redirect to the path set for the default tab if URL does not already include a valid tab-path. -
depth
{integer}[null]
optional
When NavTabs are nested, it cannot automatically determine which part of the URL is for the tabs. This can be handled by specifying which segment of the URL the tabs occupy. Set to0
for the root of the URL,1
for the second segment, and so on. -
parentPath
{string}[""]
optional
This also addresses the issue of confusing URLs that cannot be automatically parsed. In most cases, usingdepth
is easier. -
rootPath
{string}[""]
optional
Handles scenarios where one tab is the 'root' ("/") of the website.
In most cases this can be handled by just leaving the tabpath
blank.
The tabs
prop accepts an array of tab-configurations.
Each tab configuration accepts these props:
-
label
{string}[""]
required
The text to display on the tab - identical to the Material UI Tab label prop. -
path
{string}[""]
required
Set a path the same as if adding a sub-route to React Router.
Thepath
is treated as relative to the parent path unless path starts with a slash, like:"/absolute/path"
. -
exact
{boolean}[null]
optional
This is the React Router 'exact' prop. In most cases NavTabs will correctly set this automatically. -
component
{component}[null]
required
The component to display when this tab is selected.
If no component is set, a<Placeholder>
component will display. -
props
{object}[null]
optional
Props that you want passed to thecomponent
specified.
See the Configuration Example below.
Any other props will be passed-through to the
Material UI Tab component.
For example, set disabled: true
to disable a tab.
NavTabs exports a named <Tabs>
component that outputs the
Material UI Tabs markup.
This is separate so the tabs can be rendered inside a special layout or wrapper.
This component does not require any props, but you can set any prop applicable to the Material UI Tabs component. For example:
<Tabs
textColor="primary"
indicatorColor="primary"
/>
This component also accepts one special prop: TabProps
.
This lets you pass props to each of the autogenerated
Material UI Tab subcomponents.
For example:
const tabProps = {
disableRipple: true,
classes: classes.tab
}
<Tabs TabProps={tabProps} />
Note: To set different props for each <Tab>
,
add these in the tabs
config.
For example, to disable one specific tab:
const tabs = [
{
label: 'Contact Us',
path: 'contacts',
disabled: true, // Extra prop is passed-through to MUI 'Tab' component
component: ContactInfo
},
{ ... }
]
NavTabs exports a named <Content>
component that outputs all the
<Route>
components; one for each tab.
This is separate so the tab-content can be rendered separate from the tabs.
This component does not accept any props.
If NavTabs is implemented without any configuration,
sample tabs
data is used to create a quick 3-tab prototype.
Cosmetic tab props can still be applied.
import NavTabs, { Tabs, Content } from '@allpro/react-nav-tabs'
function Test() {
return (
<NavTabs>
<CustomHeader>
<Tabs
textColor="primary"
indicatorColor="primary"
TabProps={{ classes: classes.tab }}
/>
</CustomHeader>
<ContentWrapper>
<Content />
</ContentWrapper>
</NavTabs>
);
}
The configure for each tab requires a label
, path
and component
.
However a blank path
is valid; meaning it will display by default.
If a props
key is specified, these are passed to the component
.
Any unexpected props are passed-through to the <Tab>
component, like
the disabled
prop shown below.
const tabs = [
{
label: 'Company',
path: 'company',
component: CompanyDescription
},
{
label: 'Contact Us',
path: 'contacts',
disabled: true, // Extra prop is passed-through to MUI 'Tab' component
component: ContactInfo
},
{
label: 'Careers',
path: 'careers',
component: JobPostings,
props: { filter: 'current' } // Props passed to JobPostings component
}
];
function Test() {
return (
<NavTabs tabs={tabs}>
<Tabs indicatorColor="primary" />
<Content />
</NavTabs>
);
}
See more examples in the Live Demos
- create-react-library - A React component framework based on create-react-app
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.