react-tabs is a flexible and accessible library for creating tab interfaces in React applications. It provides a complete tab system with keyboard navigation, ARIA attributes, and extensive customization options. This guide walks through advanced usage of react-tabs with React, including custom configurations, controlled tabs, and complex tab patterns. This is part 48 of a series on using react-tabs with React.
Prerequisites
Before you begin, make sure you have:
- Node.js version 14.0 or higher installed
- npm, yarn, or pnpm package manager
- A React project (version 16.8 or higher) or create-react-app setup
- Basic knowledge of React hooks (useState, useCallback)
- Familiarity with JavaScript/TypeScript
- Understanding of CSS for styling
Installation
Install react-tabs using your preferred package manager:
npm install react-tabs
Or with yarn:
yarn add react-tabs
Or with pnpm:
pnpm add react-tabs
After installation, your package.json should include:
{
"dependencies": {
"react-tabs": "^5.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
Project Setup
Import react-tabs styles in your main entry file:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'react-tabs/style/react-tabs.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
First Example / Basic Usage
Let's create a simple tab interface. Create a new file src/TabsExample.jsx:
// src/TabsExample.jsx
import React from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
function TabsExample() {
return (
<div style={{ padding: '20px' }}>
<h2>Basic Tabs Example</h2>
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
</TabList>
<TabPanel>
<h3>Content for Tab 1</h3>
<p>This is the content of the first tab.</p>
</TabPanel>
<TabPanel>
<h3>Content for Tab 2</h3>
<p>This is the content of the second tab.</p>
</TabPanel>
<TabPanel>
<h3>Content for Tab 3</h3>
<p>This is the content of the third tab.</p>
</TabPanel>
</Tabs>
</div>
);
}
export default TabsExample;
Update your App.jsx:
// src/App.jsx
import React from 'react';
import TabsExample from './TabsExample';
import './App.css';
function App() {
return (
<div className="App">
<TabsExample />
</div>
);
}
export default App;
This creates a basic tab interface with three tabs and their corresponding content panels.
Understanding the Basics
react-tabs provides several key components:
- Tabs: Main container component
- TabList: Container for tab buttons
- Tab: Individual tab button
- TabPanel: Content panel for each tab
- Controlled mode: Manage tab state externally
- Keyboard navigation: Built-in arrow key navigation
- Accessibility: Full ARIA support
Key concepts for advanced usage:
-
Controlled Tabs: Use
selectedIndexandonSelectfor controlled behavior -
Default Index: Set initial tab with
defaultIndexprop -
Disabled Tabs: Disable specific tabs with
disabledprop - Custom Styling: Override default styles with CSS classes
-
Event Handlers: Use
onSelectto handle tab changes
Here's an example with controlled tabs and custom styling:
// src/ControlledTabsExample.jsx
import React, { useState } from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
function ControlledTabsExample() {
const [selectedIndex, setSelectedIndex] = useState(0);
const handleSelect = (index) => {
setSelectedIndex(index);
console.log(`Selected tab: ${index}`);
};
return (
<div style={{ padding: '20px' }}>
<h2>Controlled Tabs Example</h2>
<Tabs selectedIndex={selectedIndex} onSelect={handleSelect}>
<TabList>
<Tab>Home</Tab>
<Tab>About</Tab>
<Tab disabled>Disabled</Tab>
<Tab>Contact</Tab>
</TabList>
<TabPanel>
<h3>Home Content</h3>
<p>Welcome to the home page.</p>
</TabPanel>
<TabPanel>
<h3>About Content</h3>
<p>Learn more about us.</p>
</TabPanel>
<TabPanel>
<h3>Disabled Tab</h3>
<p>This tab is disabled.</p>
</TabPanel>
<TabPanel>
<h3>Contact Content</h3>
<p>Get in touch with us.</p>
</TabPanel>
</Tabs>
<p style={{ marginTop: '20px' }}>Selected tab index: {selectedIndex}</p>
</div>
);
}
export default ControlledTabsExample;
Practical Example / Building Something Real
Let's build a comprehensive tabbed interface with forms, data display, and settings:
// src/AdvancedTabsInterface.jsx
import React, { useState } from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
function AdvancedTabsInterface() {
const [selectedIndex, setSelectedIndex] = useState(0);
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const [data, setData] = useState([
{ id: 1, name: 'Item 1', value: 100 },
{ id: 2, name: 'Item 2', value: 200 },
{ id: 3, name: 'Item 3', value: 300 }
]);
const handleFormChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleFormSubmit = (e) => {
e.preventDefault();
alert('Form submitted!');
setFormData({ name: '', email: '', message: '' });
};
const handleSelect = (index) => {
setSelectedIndex(index);
};
return (
<div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
<h1>Advanced Tabs Interface</h1>
<Tabs
selectedIndex={selectedIndex}
onSelect={handleSelect}
selectedTabClassName="react-tabs__tab--selected"
selectedTabPanelClassName="react-tabs__tab-panel--selected"
>
<TabList style={{
display: 'flex',
borderBottom: '2px solid #ddd',
marginBottom: '20px'
}}>
<Tab style={{
padding: '10px 20px',
cursor: 'pointer',
border: 'none',
backgroundColor: 'transparent',
borderBottom: '2px solid transparent',
marginRight: '10px'
}}>
Form
</Tab>
<Tab style={{
padding: '10px 20px',
cursor: 'pointer',
border: 'none',
backgroundColor: 'transparent',
borderBottom: '2px solid transparent',
marginRight: '10px'
}}>
Data
</Tab>
<Tab style={{
padding: '10px 20px',
cursor: 'pointer',
border: 'none',
backgroundColor: 'transparent',
borderBottom: '2px solid transparent',
marginRight: '10px'
}}>
Settings
</Tab>
</TabList>
<TabPanel>
<div style={{
padding: '20px',
border: '1px solid #ddd',
borderRadius: '8px',
backgroundColor: '#f8f9fa'
}}>
<h2>Contact Form</h2>
<form onSubmit={handleFormSubmit}>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px', fontWeight: '500' }}>
Name
</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleFormChange}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
boxSizing: 'border-box'
}}
/>
</div>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px', fontWeight: '500' }}>
Email
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleFormChange}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
boxSizing: 'border-box'
}}
/>
</div>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px', fontWeight: '500' }}>
Message
</label>
<textarea
name="message"
value={formData.message}
onChange={handleFormChange}
rows={4}
style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px',
boxSizing: 'border-box',
resize: 'vertical'
}}
/>
</div>
<button
type="submit"
style={{
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Submit
</button>
</form>
</div>
</TabPanel>
<TabPanel>
<div style={{
padding: '20px',
border: '1px solid #ddd',
borderRadius: '8px',
backgroundColor: '#f8f9fa'
}}>
<h2>Data Table</h2>
<table style={{
width: '100%',
borderCollapse: 'collapse',
backgroundColor: 'white',
borderRadius: '4px',
overflow: 'hidden'
}}>
<thead>
<tr style={{ backgroundColor: '#007bff', color: 'white' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>ID</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Name</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Value</th>
</tr>
</thead>
<tbody>
{data.map(item => (
<tr key={item.id} style={{ borderBottom: '1px solid #ddd' }}>
<td style={{ padding: '12px' }}>{item.id}</td>
<td style={{ padding: '12px' }}>{item.name}</td>
<td style={{ padding: '12px' }}>${item.value}</td>
</tr>
))}
</tbody>
</table>
</div>
</TabPanel>
<TabPanel>
<div style={{
padding: '20px',
border: '1px solid #ddd',
borderRadius: '8px',
backgroundColor: '#f8f9fa'
}}>
<h2>Settings</h2>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<input type="checkbox" />
<span>Enable notifications</span>
</label>
</div>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<input type="checkbox" />
<span>Dark mode</span>
</label>
</div>
<div style={{ marginBottom: '16px' }}>
<label style={{ display: 'block', marginBottom: '4px' }}>
Language
</label>
<select style={{
width: '100%',
padding: '8px',
border: '1px solid #ddd',
borderRadius: '4px'
}}>
<option>English</option>
<option>Spanish</option>
<option>French</option>
</select>
</div>
<button
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Save Settings
</button>
</div>
</TabPanel>
</Tabs>
</div>
);
}
export default AdvancedTabsInterface;
Add custom styles in App.css:
/* src/App.css */
.react-tabs {
-webkit-tap-highlight-color: transparent;
}
.react-tabs__tab-list {
border-bottom: 2px solid #ddd;
margin: 0 0 20px;
padding: 0;
}
.react-tabs__tab {
display: inline-block;
border: none;
bottom: -2px;
position: relative;
list-style: none;
padding: 10px 20px;
cursor: pointer;
background-color: transparent;
border-bottom: 2px solid transparent;
margin-right: 10px;
}
.react-tabs__tab--selected {
background: transparent;
border-color: #007bff;
color: #007bff;
border-radius: 0;
border-bottom: 2px solid #007bff;
}
.react-tabs__tab--disabled {
color: #ccc;
cursor: not-allowed;
}
.react-tabs__tab:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.3);
}
.react-tabs__tab-panel {
display: none;
}
.react-tabs__tab-panel--selected {
display: block;
}
Update your App.jsx:
// src/App.jsx
import React from 'react';
import AdvancedTabsInterface from './AdvancedTabsInterface';
import './App.css';
function App() {
return (
<div className="App">
<AdvancedTabsInterface />
</div>
);
}
export default App;
This example demonstrates:
- Controlled tabs with state management
- Form in a tab panel
- Data table in a tab panel
- Settings panel in a tab
- Custom styling
- Keyboard navigation support
Common Issues / Troubleshooting
Tabs not switching: Make sure you're using
TabPanelcomponents for eachTab. The number ofTabcomponents should match the number ofTabPanelcomponents.Styling not applying: Import the CSS file (
import 'react-tabs/style/react-tabs.css'). You can also override styles using CSS classes or inline styles.Controlled tabs not working: When using controlled mode, make sure you're providing both
selectedIndexandonSelectprops. TheonSelecthandler should update the state.Keyboard navigation not working: react-tabs includes keyboard navigation by default. Make sure the tabs are focused. Use Tab key to navigate between tabs and arrow keys to switch tabs.
Disabled tabs still clickable: Use the
disabledprop on theTabcomponent to disable it. Disabled tabs won't respond to clicks or keyboard navigation.Accessibility warnings: react-tabs includes ARIA attributes by default. If you see accessibility warnings, make sure you're using the components correctly and not overriding ARIA attributes unnecessarily.
Next Steps
Now that you have an advanced understanding of react-tabs:
- Explore advanced customization options and theming
- Learn about nested tabs and complex tab structures
- Implement custom tab components and animations
- Add tab persistence and URL synchronization
- Integrate with React Router for navigation
- Learn about other tab libraries (react-tabs, reach-ui tabs)
- Check the official repository: https://github.com/reactjs/react-tabs
- Look for part 49 of this series for more advanced topics
Summary
You've successfully integrated react-tabs into your React application with advanced features including controlled tabs, custom styling, form integration, and comprehensive tab interfaces. react-tabs provides a flexible, accessible solution for creating tab interfaces with full keyboard navigation support.
SEO Keywords
react-tabs
React tab component
react-tabs tutorial
React tab interface
react-tabs installation
React accessible tabs
react-tabs example
React tab navigation
react-tabs setup
React controlled tabs
react-tabs customization
React tab library
react-tabs keyboard navigation
React tab panels
react-tabs getting started
Top comments (0)