Accordion Menu using React

Accordion Menu using React

Designing a Simple and Responsive Accordion Menu with React and Tailwind CSS

Accordion is a commonly used project in web development that enables developers to create accordion menus, which are collapsible sections of content that can be expanded and collapsed by clicking on a header.

In this blog, we will build a simple and responsive Accordion Menu about the James Webb Telescope with the help of React and Tailwind.

Our Accordion Menu will have three components:

🪗Data Component

We will create a questions array in the data component which will contain an array of objects, where each object will represent a single question and its answer along with the following properties:

  • id : A unique identifier.

  • title : the question.

  • info : the answer.

const questions = [
  {
    id: 1,
    title: 'When was James Webb Space Telescope launched?',
    info:
      'The James Webb Space Telescope was launched on December 25, 2021, from Kourou, French Guiana. It arrived at the Sun-Earth L2 Lagrange Point in January 2022.',
  },
  {
    id: 2,
    title: 'Which rocket launched James Webb Space Telescope?',
    info:
    'NASA’s James Webb Space Telescope was launched on an Ariane 5 rocket. It is a European heavy-lift space launch vehicle which is developed and operated by Arianespace for the European space Agency (ESA).',
  },
  {
    id: 3,
    title: 'How much did the James Webb Space Telescope cost?',
    info:
      'The James Webb Space Telescopes  major redesign in 2005 led to the current approach, with the construction completed in 2016 at a total cost of USD 10 billion.',
  },
  {
    id: 4,
    title: 'James Webb Space Telescope is named after which person?',
    info:
      'James Webb Space Telescope is named after James E. Webb. He was the administrator of NASA from 1961 to 1968 during the Mercury, Gemini and Apollo Programs.',
  },
  {
    id: 5,
    title: ' When were the first images from James Webb Space Telescope released?',
    info:
      'The first images from the James Webb Space Telescope was released to the public via a press conference on July 11, 2022.',
  },
]
export default questions

We will then export this array and use it in the Accordion Component.

🪗Question Component

Now, let's create another component that will render the title and answer of the question and a button to toggle the visibility of the answer information.

We'll define a component called Question, which will take in title and info props. Let's also import the useState hook to create a showInfo state variable and a setShowInfo function to toggle the visibility of the info text.

We'll also be using react-icons which you can install using:

npm:

npm install react-icons --save

or yarn:

yarn add react-icons

After installing them, import the following icons from the react-icons library.

The component will return an article element, within which there will a header element with an h4 tag displaying the title prop, and a button element that will toggle the showInfo state when clicked.

import React, { useState } from 'react';
import { AiOutlineMinus, AiOutlinePlus } from 'react-icons/ai';
const Question = ({ title, info }) => {
  const [showInfo, setShowInfo] = useState(false);
  return (
    <article>
      <header>
        <h4>{title}</h4>
        <button className='btn' onClick={() => setShowInfo(!showInfo)}>
          {showInfo ? <AiOutlineMinus /> : <AiOutlinePlus />}
        </button>
      </header>
      {showInfo && <p>{info}</p>}
    </article>
  );
};

export default Question;

Depending on the state of showInfo, the button displays either a minus(-) or plus(+) icon from the react-icons/ai library.

Finally, if showInfo is true, the info prop is displayed inside a p tag.

🪗Accordion Component

Let's import the data component and the SingleQuestion component from Question component. We'll again use the useState hook to initialize the questions state with the data array.

Inside the return statement, we will render the main content of the application. We'll have a div with a h3 heading and a section containing the questions and answers. We'll render the questions by mapping through the questions state using questions.map().

import React, { useState } from 'react';
import data from './data';
import SingleQuestion from './Question';
function Accordion() {
  const [questions, setQuestions] = useState(data);
  return (
    <main>
      <div>
        <h3>James Webb Space Telescope FAQs</h3>
        <section>
          {questions.map((question) => {
            return (
              <SingleQuestion key={question.id} {...question}></SingleQuestion>
            );
          })}
        </section>
      </div>
    </main>
  );
}

export default Accordion;

For each question, a SingleQuestion component is rendered, where we passed in the key and the spread props of the question object. The key prop is used to keep track of each question in the list, and the spread props are used to pass in the id, title, and info values of the question object as props to the SingleQuestion component.

Adding Tailwind

Let's add Tailwind CSS to both our Question and Accordion Component. We will ensure that the Accordion Menu is responsive to different media sizes. You can also change the values or add new ones to suit your preferences.

Question Component with Tailwind

import React, { useState } from 'react';
import { AiOutlineMinus, AiOutlinePlus } from 'react-icons/ai';

const Question = ({ title, info }) => {
  const [showInfo, setShowInfo] = useState(false);
  return (
    <article class='py-4 px-6 mb-5 rounded-md shadow-md hover:shadow-slate-500 bg-yellow-500 text-black'>
      <header class='flex justify-between items-center'>
        <h4 class='text-base md:text-lg font-mono font-bold leading-6 tracking-wider mr-4'>
          {title}
        </h4>
        <button class='sm:w-6 sm:h-6 md:w-8 md:h-8 p-1 md:p-2 rounded-full bg-slate-800 text-yellow-500 cursor-pointer flex justify-center items-center' onClick={() => setShowInfo(!showInfo)}>
          {showInfo ? <AiOutlineMinus /> : <AiOutlinePlus />}
        </button>
      </header>
      {showInfo && <p class='my-3 mr-10 font-semibold'>{info}</p>}
    </article>
  );
};

export default Question;

Accordion Component with Tailwind

You can add a custom background image in the tailwind.config.js file using the extend property:

  theme: {
    extend: {
       backgroundImage: {
        'space': "url('https://economictimes.indiatimes.com/thumb/msid-96270449,width-3000,height-1732,resizemode-4,imgsize-949414/james-webb-space-telescope.jpg?from=mdr')",
      },
    },
  },
  plugins: [],
}

We'll give it a custom name: space and use it as follows:

import React, { useState } from 'react';
import data from './data.js';
import SingleQuestion from './Question1.jsx';

function Accordion() {
 const [questions, setQuestions] = useState(data);
  return (
    <main class='min-h-screen bg-space bg-cover flex justify-center items-center'>
      <div class='w-10/12 max-w-4xl mx-auto rounded-md py-12 px-8 lg:flex lg:items-center border border-yellow-500  bg-gradient-to-r from-slate-900 to-black'>
        <h3 class='text-center text-xl md:text-3xl font-semibold tracking-wide italic text-white font-mono mb-10  lg:mb-0'>James Webb Space Telescope FAQs</h3>
        <section>
          {questions.map((question) => {
            return (
              <SingleQuestion key={question.id} {...question}></SingleQuestion>
            );
          })}
        </section>
      </div>
    </main>
  );
}

export default Accordion;

Import the Accordion component into your App.jsx component, run the server, and check out the output:

PS: Open the image in a new tab.

Conclusion

We've just created a responsive Accordion Menu about the James Webb Space Telescope.

Together, these three components form a FAQ page that can display the questions and answers dynamically and also allows each question to be expanded or collapsed individually.


Thank's for taking the time to read this blog.

Catch you guys on the next one. Cheers .. ✌️

Did you find this article valuable?

Support Raj Sarkar by becoming a sponsor. Any amount is appreciated!