Create A Reusable Tabs Component In React
Hey guys! Let's dive into creating a reusable Tabs component in React. This component will help us streamline navigation between different sections or views within a page, ensuring consistency and a better user experience across our application. We'll cover everything from the basic setup to advanced features like keyboard navigation and accessibility.
Overview
Tab navigation is a common pattern in modern web applications. You've probably seen it in settings pages, achievement sections, and many other places. The goal here is to create a standardized Tabs component in our UI library to ensure consistency. Currently, tab-like navigation is implemented inconsistently across different parts of our application, like in the Settings and Achievements pages. By creating a single, reusable component, we can avoid duplication and maintain a unified look and feel.
Context
Right now, different areas of our application use different implementations for tab navigation. This inconsistency can lead to a fragmented user experience and makes it harder to maintain and update our codebase. For example, the Settings page and the Achievements page both use tab navigation, but they don't use the same code. By creating a reusable Tabs component, we can ensure that all tab navigation follows the same standards.
Task: Create Tabs Component
File to Create
We'll start by creating a new file for our Tabs component:
/src/components/ui/Tabs.tsx
Component Requirements
Let's outline the requirements for our Tabs component. This includes the props it should accept, the features it should implement, and the overall functionality it should provide.
Props Interface:
The component should accept the following props:
value: string: The currently active tab's value.onValueChange: (value: string) => void: A callback function to update the active tab's value.tabs: Array<{value: string, label: string, icon?: ReactNode}>: An array of tab objects, each with a value, a label, and an optional icon.children: ReactNode: The content to display within the active tab.orientation?: 'horizontal' | 'vertical': An optional prop to specify the tab orientation (horizontal or vertical). Defaults to horizontal.
Features to Implement:
Here are the features we need to implement in our Tabs component:
- Controlled tabs with value/onValueChange: The component should be controlled, meaning the active tab is determined by the
valueprop and updated via theonValueChangecallback. - Active tab indicator/underline: There should be a visual indicator (like an underline or background color) to show which tab is currently active.
- Smooth transitions between tabs: When switching between tabs, there should be a smooth transition effect to enhance the user experience.
- Optional icons in tabs: Each tab should be able to display an optional icon next to its label.
- Keyboard navigation (arrow keys): Users should be able to navigate between tabs using the left and right arrow keys.
- ARIA attributes for accessibility: The component should include ARIA attributes to make it accessible to users with disabilities.
- Horizontal and vertical layouts: The component should support both horizontal and vertical layouts, depending on the
orientationprop.
Task: Find Tab Patterns
Before we start migrating existing tab navigation to our new Tabs component, we need to identify where tab-like navigation is currently used in our application. We'll focus on the Settings and Achievements pages first. Look for any instances of tabbed interfaces and note how they are implemented.
Migration Steps
Once we have our Tabs component ready, we can start migrating existing tab navigation to use it. Here are the steps we'll follow:
-
Import Tabs component: Import the Tabs component into the file where you want to use it.
import Tabs from './components/ui/Tabs'; -
Convert tab navigation to Tabs format: Replace the existing tab navigation code with our new Tabs component.
-
Map value/onValueChange: Connect the Tabs component to the appropriate state and update functions in your component.
-
Test keyboard navigation: Make sure that keyboard navigation works correctly after the migration.
Example Migration
Let's say you have the following code in your Settings page:
import React, { useState } from 'react';
function Settings() {
const [activeTab, setActiveTab] = useState('general');
return (
<div>
<ul>
<li
className={activeTab === 'general' ? 'active' : ''}
onClick={() => setActiveTab('general')}
>
General
</li>
<li
className={activeTab === 'profile' ? 'active' : ''}
onClick={() => setActiveTab('profile')}
>
Profile
</li>
<li
className={activeTab === 'security' ? 'active' : ''}
onClick={() => setActiveTab('security')}
>
Security
</li>
</ul>
{activeTab === 'general' && <div>General Settings Content</div>}
{activeTab === 'profile' && <div>Profile Settings Content</div>}
{activeTab === 'security' && <div>Security Settings Content</div>}
</div>
);
}
export default Settings;
Here's how you would migrate it to use the Tabs component:
import React, { useState } from 'react';
import Tabs from './components/ui/Tabs';
function Settings() {
const [activeTab, setActiveTab] = useState('general');
const tabs = [
{ value: 'general', label: 'General' },
{ value: 'profile', label: 'Profile' },
{ value: 'security', label: 'Security' },
];
return (
<Tabs value={activeTab} onValueChange={setActiveTab} tabs={tabs}>
{activeTab === 'general' && <div>General Settings Content</div>}
{activeTab === 'profile' && <div>Profile Settings Content</div>}
{activeTab === 'security' && <div>Security Settings Content</div>}
</Tabs>
);
}
export default Settings;
Acceptance Criteria
To ensure our Tabs component meets the required standards, we'll use the following acceptance criteria:
- Tabs component created: The Tabs.tsx file exists and contains a functional Tabs component.
- Settings page migrated: The Settings page has been updated to use the Tabs component.
- Achievements page migrated: The Achievements page has been updated to use the Tabs component.
- Keyboard navigation works: Users can navigate between tabs using the arrow keys.
- Component is accessible: The component includes ARIA attributes and is accessible to users with disabilities.
By following these steps, we can create a reusable and accessible Tabs component that enhances the user experience across our application.
External Link: For more information on React accessibility, check out the WAI-ARIA basics.