TAB Component with ReactJS

Welcome, my name is Hugo Ferreira! Today, I'm here to teach you how to create a TAB component with ReactJS!

Observation: I created this post considering that you know the basics of ReactJS. If you see anything wrong, please tell me!

You can see it working at CodePen: https://codepen.io/huferr/pen/GRmZJJx

To do this, we will use a functional component called Tab. This component will return the HTML content. Let's define it:

const Tab = () => {
  return (
    <div className="container">
      <ul className="tab-list">
        <li className="tabs active-tabs">Tab 1</li>
        <li className="tabs">Tab 2</li>
        <li className="tabs">Tab 3</li>
      </ul>
      <div className="content-container">
        <div className="content active-content"><h2>Lorem</h2></div>
        <div className="content"><h2>Ipsum</h2></div>
        <div className="content"><h2>Dolor</h2></div>
      </div>
    </div>
  );
};

Observe the classes called active-tabs and active-content in our first tab and content elements. These classes will define which component should or should not be shown, and we'll use CSS to make this happen.

What will make the tab change effect is the active-tabs class. When called, the style of the tab will change, making it "visible". Look the example:

Here's the CSS file:

.container {
  width: 400px;
  height: 250px;
  background-color: #eeeded;
  border: 1px solid rgba(0, 0, 0, 0.3);
}

.tab-list {
  height: 50px;
  display: flex;
  list-style: none;
  font-size: 18px;
  padding: 0;
  margin: 0;
}

.tabs {
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #80808013;
  position: relative;
  cursor: pointer;
}

.tabs:not(:last-child) {
  border-right: 1px solid rgba(0, 0, 0, 0.3);
}

.active-tabs {
  background: #eeeded;
}

.active-tabs::before {
  content: "";
  display: block;
  position: absolute;
  top: -4px;
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% + 2px);
  height: 4px;
  background: #5893f1;
}

.content {
    display: none;
    background-color: #eeeded;
    padding: 10px;
}

.active-content {
    display: flex;
}

As you can see, the tabs class has a background to represent that it has not been selected. So, when we put the active-tabs class, the tab style looks like it's selected.

Looking at the content class, we can see display: none, which will "hide" the content from the screen, and it will only show when we call active-content, which has display: flex. This will make the content appear.

What we have to do now is create a way to control these classes when we click on each tab, binding the element that has the active-tabs class with the element that has the active-content class.

To do that, let's import useState Hook and set our toggleState, which will handle the index of each tab we have.

Obs.: Do it in the same Tab component.

import React, { useState } from "react";
const Tab = () => {

    const [toggleState, setToggleState] = useState(1)

  return (

Now, let's define an Index for each tab we have (3).

// Tab 1 = index 1
// Tab 2 = index 2, and so on...

To make it easier to understand, let's create a function that will set the index every time we click in each tab:

const toggleTab = (index) = {
        setToggleState(index)
    }

Then, create an onClick event on each tab. Call an anonymous function with our toggleTab function. So, for each tab, let's define an index:

<ul className="tab-list">
        <li className="tabs active-tabs" onClick={() => toggleTab(1)}>Tab 1</li>
        <li className="tabs"onClick={() => toggleTab(2)}>Tab 2</li>
        <li className="tabs"onClick={() => toggleTab(3)}>Tab 3</li>
      </ul>

Finally, let's control the classes! For this, let's use a ternary operator inside className="":

<ul className="tab-list">
        <li className={toggleState === 1 ? 'tabs active-tabs' : "tabs"} onClick={() => toggleTab(1)}>Tab 1</li>
        <li className={toggleState === 2 ? 'tabs active-tabs' : "tabs"} onClick={() => toggleTab(2)}>Tab 2</li>
        <li className={toggleState === 3 ? 'tabs active-tabs' : "tabs"} onClick={() => toggleTab(3)}>Tab 3</li>
      </ul>

Now, let's do it for the content:

<div className="content-container">
        <div className={toggleState === 1 ? 'content active-content' : "content"}><h2>Lorem</h2></div>
        <div className={toggleState === 2 ? 'content active-content' : "content"}><h2>Ipsum</h2></div>
        <div className={toggleState === 3 ? 'content active-content' : "content"}><h2>Dolor</h2></div>
      </div>

Basically, we are saying that if toggleState is 1, put the class tabs and active-tabs in the Tab 1. if toggleState is 2, put the class tabs and active-tabs in the Tab 2. If not, put only tabs Same for the content classes.

In order to make it better, let's create a function to do this comparison:

const getActiveClass = (index, className) =>
    toggleState === index ? className : "";

Overview:

import React, { useState } from "react";
import "./styles.css";

const Tab = () => {
  const [toggleState, setToggleState] = useState(1);

  const toggleTab = (index) => {
    setToggleState(index);
  };

  const getActiveClass = (index, className) =>
    toggleState === index ? className : "";

  return (
    <div className="container">
      <ul className="tab-list">
        <li
          className={`tabs ${getActiveClass(1, "active-tabs")}`}
          onClick={() => toggleTab(1)}
        >
          Tab 1
        </li>
        <li
          className={`tabs ${getActiveClass(2, "active-tabs")}`}
          onClick={() => toggleTab(2)}
        >
          Tab 2
        </li>
        <li
          className={`tabs ${getActiveClass(3, "active-tabs")}`}
          onClick={() => toggleTab(3)}
        >
          Tab 3
        </li>
      </ul>
      <div className="content-container">
        <div className={`content ${getActiveClass(1, "active-content")}`}>
          <h2>Lorem</h2>
        </div>
        <div className={`content ${getActiveClass(2, "active-content")}`}>
          <h2>Ipsum</h2>
        </div>
        <div className={`content ${getActiveClass(3, "active-content")}`}>
          <h2>Dolor</h2>
        </div>
      </div>
    </div>
  );
};

export default Tab;

Results

Done! Thanks for reading this content, I hope it helps you in some way and, if you notice something wrong, feel free to help me leaving a comment bellow or find me on twitter !

You can also find me at:

22