Vertical Tabs with React Router
Tags: react, typescript
Published: 2023-04-23 06:52:20

This is an idea to implement tabs with React Router (v6) and [styled-components](https://www.styled-components.com/). ([demo](https://s1ty7g.csb.app/home))

![tabs image](https://cdn-images-1.medium.com/max/2000/1*ZUVmT7rFuMgqF4PY32CaiQ.gif)

## Overview

* Use React Router to switch panels

* Use React Router NavLink as a Tab

* Each panel is a Route whose element is TabPanel

![](https://cdn-images-1.medium.com/max/4332/1*7d9CxKzBiZSInXAQ09pbrA.png)

## Tabs

### Tabs.tsx
```typescript
    import React from "react";
    import { TabContainer, TabPanelContainer } from "./Tabs.styles";
    import { TabListType } from "../../data/tab-lists";
    import TabList from "../TabList/TabList";
    
    type TabsProps = {
      children: JSX.Element;
      tabLists: TabListType[];
    };
    
    const Tabs = ({ children, tabLists }: TabsProps) => {
      return (
        <TabContainer>
          <TabList tabLists={tabLists} />
          <TabPanelContainer>{children}</TabPanelContainer>
        </TabContainer>
      );
    };
    
    export default Tabs;
```
### Tabs.styles.tsx
```typescript
    import styled from "styled-components";
    
    type TabPanelProps = {
      height?: string;
    };
    
    export const TabContainer = styled.div`
      display: grid;
      grid-template-columns: 120px auto;
    `;
    export const TabPanelContainer = styled.div`
      overflow-y: scroll;
      height: ${({ height = "100vh" }: TabPanelProps) => height};
    `;
```
## TabList

### TabList.tsx
```typescript
    import React from "react";
    import { TabListType } from "../../data/tab-lists";
    import { TabListContainer, StyledNavLink } from "./TabList.styles";
    
    type TabListProps = {
      tabLists: TabListType[];
    };
    
    const TabList = ({ tabLists }: TabListProps) => {
      return (
        <TabListContainer>
          {tabLists.map((TabList) => (
            <StyledNavLink key={TabList.tabKey} to={TabList.tabKey}>
              {TabList.title}
            </StyledNavLink>
          ))}
        </TabListContainer>
      );
    };
    
    export default TabList;
```
### TabList.styles.tsx

I made use of the default active class to style the active navigation state. (ref: [https://reactrouter.com/en/main/components/nav-link#default-active-class](https://reactrouter.com/en/main/components/nav-link#default-active-class))
```typescript
    import styled from "styled-components";
    import { NavLink } from "react-router-dom";
    
    type TabListContainerProps = {
      height?: string;
    };
    
    export const TabListContainer = styled.div`
      display: flex;
      flex-direction: column;
      overflow-y: scroll;
      height: ${({ height = "100vh" }: TabListContainerProps) => height};
    `;
    
    export const StyledNavLink = styled(NavLink)`
      display: block;
      color: black;
      text-transform: capitalize;
      text-align: center;
      text-decoration: none;
      padding: 5px;
      background-color: #efefef;
      &.active {
        border-left: 3px solid black;
        background-color: white;
      }
    `;
```
## TabPanel

### TabPanel.tsx
```typescript
    import React from "react";
    import { TabPanelContainer } from "./TabPanel.styles";
    
    type TabPanelProps = {
      title: string;
    };
    
    const TabPanel = ({ title }: TabPanelProps) => {
      return (
        <TabPanelContainer>
          <h1>{title}</h1>
        </TabPanelContainer>
      );
    };
    
    export default TabPanel;
```
### TabPanel.styles.tsx
```typescript
    import styled from "styled-components";
    
    export const TabPanelContainer = styled.div`
      padding: 10px;
    `;
```
## App.tsx
```typescript
    import "./styles.css";
    import { Routes, Route, Navigate } from "react-router-dom";
    import Tabs from "./components/Tabs/Tabs";
    import TabPanel from "./components/TabPanel/TabPanel";
    import { tabLists } from "./data/tab-lists";
    
    export default function App() {
      return (
        <Tabs tabLists={tabLists}>
          <Routes>
            {tabLists.map((tabList) => (
              <Route
                key={tabList.tabKey}
                path={tabList.tabKey}
                element={<TabPanel title={tabList.title} />}
              />
            ))}
            <Route path="*" element={<Navigate to="home" />} />
          </Routes>
        </Tabs>
      );
    }
```
That’s it!

As a side note, I created the mock tabList with chatGPT.

The entire code is available [here](https://codesandbox.io/s/floral-browser-s1ty7g?file=/src/App.tsx:0-613).
The original article is [here](https://medium.com/@lada496/vertical-tabs-with-react-router-98b602e056cd)