Tab Selector

Create a component with multiple tabs for users to click through. Display different content as each tab is selected.

Solution

  • One
  • Two
  • Three
This is the first section.

Explanation

The HTML Structure

The tabs are stored in an unordered list. Each list item has an onClick function and a dynamic class name.

The content is handled through an object lookup.

The activeTab state

The activeTab value is stored in state and is set via the clickHandler function.

The clickHandler function

When a tab is clicked, it's name is set in state.

Conditional styling for tabs

Each list item shares basic styles and the active style is added conditionally based on the value of activeTab.

The dynamic content

For speed and reduced complexity, the content for each tab is stored in an object. In the section element, content[activeTab] uses the activeTab as the object key to return the correct content.

Code

import { useState } from "react";
import styles from "./Solution.module.css";

const Solution = () => {
  type tabProps = "One" | "Two" | "Three";

  const [activeTab, setActiveTab] = useState<tabProps>("One");

  const clickHandler = (tab: tabProps) => {
    setActiveTab(tab);
  };

  return (
    <div>
      <ul className={styles.list}>
        <li
          onClick={() => clickHandler("One")}
          className={`${styles.listItem} ${
            activeTab === "One" ? styles.active : ""
          }`}
        >
          One
        </li>
        <li
          onClick={() => clickHandler("Two")}
          className={`${styles.listItem} ${
            activeTab === "Two" ? styles.active : ""
          }`}
        >
          Two
        </li>
        <li
          onClick={() => clickHandler("Three")}
          className={`${styles.listItem} ${
            activeTab === "Three" ? styles.active : ""
          }`}
        >
          Three
        </li>
      </ul>
      <section className={styles.content}>{content[activeTab]}</section>
    </div>
  );
};

export default Solution;

const content: { [key: string]: string } = {
  One: "This is the first section.",
  Two: "This is the second section.",
  Three: "This is the third section.",
};

Styling

.list {
  display: flex;
  gap: 5px;
}

.listItem {
  padding: 5px;
  border: 1px solid grey;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.listItem:hover,
.listItem:active {
  background-color: rgb(212, 179, 135);
  color: black;
}

.active {
  background-color: rgb(71, 169, 114);
  color: white;
}

.content {
  margin-top: 20px;
}

Links