Vertical Tabs with React Router

Yuko - Apr 23 '23 - - Dev Community

This is an idea to implement tabs with React Router (v6) and styled-components. (demo)

tabs image

Overview

  • Use React Router to switch panels

  • Use React Router NavLink as a Tab

  • Each panel is a Route whose element is TabPanel

Tabs

Tabs.tsx

    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;
Enter fullscreen mode Exit fullscreen mode

Tabs.styles.tsx

    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};
    `;
Enter fullscreen mode Exit fullscreen mode

TabList

TabList.tsx

    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;
Enter fullscreen mode Exit fullscreen mode

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)

    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;
      }
    `;
Enter fullscreen mode Exit fullscreen mode

TabPanel

TabPanel.tsx

    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;
Enter fullscreen mode Exit fullscreen mode

TabPanel.styles.tsx

    import styled from "styled-components";

    export const TabPanelContainer = styled.div`
      padding: 10px;
    `;
Enter fullscreen mode Exit fullscreen mode

App.tsx

    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>
      );
    }
Enter fullscreen mode Exit fullscreen mode

That’s it!

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

The entire code is available here.
The original article is here

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player