Skip to content

arnobt78/Accordion-Display--React-Fundamental-Project-4

Repository files navigation

Accordion Display - React, Vite, JavaScript, Custom CSS Fundamental Project 4

License: MIT React Vite JavaScript react-icons

An interactive React application that demonstrates core React concepts through an Accordion UI—a set of questions with toggleable answers. This project is ideal for learners who want to strengthen their understanding of React state management, component structure, and event handling. Use it as a reference for building FAQ sections, collapsible content, or any expand/collapse interface.

Screenshot 2026-03-10 at 16 29 43

Table of Contents

  1. Project Summary
  2. Features
  3. Technology Stack
  4. Project Structure
  5. Getting Started
  6. Environment Variables (.env)
  7. Component Overview & Walkthrough
  8. How It Works
  9. API, Backend & Data
  10. Routes & Navigation
  11. Code Walkthrough & Teaching Content
  12. Reusing Components in Other Projects
  13. Functionalities & Features in Detail
  14. Keywords & Learning Outcomes
  15. Conclusion
  16. License

Project Summary

This project is a fundamental React exercise focused on building a dynamic Accordion (FAQ / Q&A) interface. It covers:

  • Functional components and component composition
  • State management with the useState hook
  • Props and data flow from parent to child
  • Conditional rendering (show/hide answer based on state)
  • Event handling (click to toggle)
  • Iterating over data (mapping an array to components)

There is no backend or API—all content comes from a local data file. The app is a single-page experience with no routing. You can run it locally for learning, teaching, or as a starting point for your own FAQ or accordion UI.


Features

  • Accordion behavior: List of questions; click to expand/collapse each answer.
  • Per-item state: Each question manages its own open/closed state with useState.
  • Visual feedback: Toggle icon switches between plus (+) and minus (-) from react-icons.
  • Single-page UI: No routing; one main view with the questions list.
  • Modern styling: Custom CSS with variables, shadows, and responsive-friendly layout.
  • Modular structure: Separate components for the list and for each question item.
  • Static data: FAQ content lives in src/data.js; no server or environment variables required to run.

Technology Stack

Technology Purpose
React 18 UI library; components and hooks
Vite 4 Dev server, HMR, and production build
JavaScript (ES6+) No TypeScript; plain JS with modules
react-icons Plus/minus icons for accordion toggle
Custom CSS Styling in src/index.css (no CSS framework)

Tooling: ESLint for linting; no testing framework in this repo.


Project Structure

04-accordion/
├── index.html              # Entry HTML; root for Vite
├── package.json            # Dependencies and scripts
├── vite.config.js          # Vite configuration
├── eslint.config.js        # ESLint (flat config)
├── .gitignore
├── README.md
├── public/
│   └── vite.svg            # Favicon / default asset
└── src/
    ├── main.jsx            # React entry; mounts App into #root
    ├── App.jsx             # Root component; holds questions state, renders Questions
    ├── Questions.jsx        # Renders list of SingleQuestion items
    ├── SingleQuestion.jsx  # One accordion item (title, toggle button, answer)
    ├── data.js             # Array of question objects (id, title, info)
    └── index.css           # Global and component styles

Notes:

  • No /routes or /pages: Single page only.
  • No /api or backend: Data is static in data.js.
  • No /hooks or /utils: Kept minimal for teaching.

Getting Started

Prerequisites

  • Node.js (v16+ recommended; v18+ preferred)
  • npm (or yarn/pnpm)

Installation & Run

  1. Clone the repository

    git clone https://github.com/arnobt78/Accordion--React-Fundamental-Project-4.git
    cd Accordion--React-Fundamental-Project-4
  2. Install dependencies

    npm install
  3. Start the development server

    npm run dev

    The app will be at http://localhost:5173 (or the next free port if 5173 is in use).

  4. Build for production

    npm run build

    Output goes to the dist/ folder. To preview the production build:

    npm run preview
  5. Lint

    npm run lint

Environment Variables (.env)

This project does not use any environment variables. All content is in src/data.js, and there are no API keys or backend URLs to configure.

If you extend the project (e.g. fetch FAQs from an API), you can use Vite’s env support:

  1. Create a .env file in the project root (same level as package.json).

  2. Define variables with the VITE_ prefix so they are exposed to the client:

    VITE_API_URL=https://api.example.com
    VITE_APP_TITLE=Accordion Display
  3. Use them in code via import.meta.env:

    const apiUrl = import.meta.env.VITE_API_URL;
    const title = import.meta.env.VITE_APP_TITLE;
  4. Optional: Add .env.example (without secrets) and document required variables for others:

    VITE_API_URL=
    VITE_APP_TITLE=Accordion Display
  5. Keep .env out of Git. This repo’s .gitignore already includes .env, so secrets are not committed.


Component Overview & Walkthrough

Component File Role
App src/App.jsx Holds questions state (from data.js), renders <Questions questions={questions} />.
Questions src/Questions.jsx Receives questions prop; maps each item to <SingleQuestion> with a unique key.
SingleQuestion src/SingleQuestion.jsx One accordion item: title, toggle button (plus/minus), and conditionally rendered answer.

Data flow:

  1. App loads the questions array (from data.js) into state.
  2. App passes the array to Questions as the questions prop.
  3. Questions maps over questions and passes each object (e.g. id, title, info) to SingleQuestion.
  4. Each SingleQuestion keeps local state showInfo (boolean) and toggles it on button click, showing or hiding the answer.

How It Works

  1. Entry: index.html loads /src/main.jsx. main.jsx renders <App /> inside <React.StrictMode> into #root and imports index.css.
  2. Data: App initializes state with useState(data) from data.js. Data is an array of { id, title, info }.
  3. List: Questions receives questions and renders one SingleQuestion per item, spreading {...question} so each gets id, title, info.
  4. Toggle: Inside SingleQuestion, showInfo starts as false. Clicking the header button calls setShowInfo(!showInfo). The answer is rendered only when showInfo is true; the icon switches between plus and minus.
  5. Styling: index.css provides layout, colors (CSS variables), and accordion look (e.g. card, shadow, button). No separate CSS modules or component CSS files.

API, Backend & Data

  • API: None. No REST or GraphQL calls.
  • Backend: None. The app is fully client-side.
  • Data: All content is in src/data.js—a default-exported array of objects. To change FAQs, edit that file or replace it with data from your own source (e.g. after adding fetch and optional env vars as in the Environment Variables section).

Routes & Navigation

  • Routes: None. Single page only; no React Router or path-based routing.
  • Navigation: No internal links or route changes. The only interaction is expanding/collapsing accordion items.

Code Walkthrough & Teaching Content

1. Entry point (src/main.jsx)

The app is mounted into the DOM and global styles are applied:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
);

Teaching notes: createRoot is the React 18 API. StrictMode helps catch side-effect and deprecation issues during development.


2. Root component (src/App.jsx)

State is initialized from the data module and passed down:

import { useState } from "react";
import data from "./data";
import Questions from "./Questions";

function App() {
  const [questions] = useState(data);
  return (
    <main>
      <Questions questions={questions} />
    </main>
  );
}

export default App;

Teaching notes: useState(data) uses the imported array as initial state. Here we only need the getter; the setter is omitted because we do not update the list in this demo. To support adding/editing questions later, you would keep the setter and pass a callback or update logic.


3. Data shape (src/data.js)

Each item has id, title, and info:

const questions = [
  {
    id: 1,
    title: "Do I have to allow the use of cookies?",
    info: "Unicorn vinyl poutine brooklyn, next level direct trade iceland...",
  },
  // ... more items
];
export default questions;

Teaching notes: id is used as the key when mapping in Questions.jsx. Keeping a stable, unique key helps React’s reconciliation and avoids subtle bugs when list order or content changes.


4. List component (src/Questions.jsx)

Receives the array and maps to presentational components:

import SingleQuestion from "./SingleQuestion";

const Questions = ({ questions }) => {
  return (
    <section className="container">
      <h1>Questions</h1>
      {questions.map((question) => {
        return <SingleQuestion key={question.id} {...question} />;
      })}
    </section>
  );
};
export default Questions;

Teaching notes: Destructuring { questions } from props is optional but clear. key={question.id} is required for list items. {...question} passes id, title, and info to each SingleQuestion.


5. Single accordion item (src/SingleQuestion.jsx)

Local state controls visibility; icon and answer depend on that state:

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

const SingleQuestion = ({ title, info }) => {
  const [showInfo, setShowInfo] = useState(false);
  return (
    <article className="question">
      <header>
        <h5>{title}</h5>
        <button className="question-btn" onClick={() => setShowInfo(!showInfo)}>
          {showInfo ? <AiOutlineMinus /> : <AiOutlinePlus />}
        </button>
      </header>
      {showInfo && <p>{info}</p>}
    </article>
  );
};

export default SingleQuestion;

Teaching notes:

  • useState: showInfo is local to each instance, so each accordion item opens/closes independently.
  • Conditional rendering: {showInfo && <p>{info}</p>} only renders the answer when showInfo is true.
  • Event handler: onClick={() => setShowInfo(!showInfo)} toggles the boolean.
  • Icons: From react-icons/ai; you can swap for other icon sets or SVGs.

6. Styling (src/index.css)

The CSS uses custom properties for theming and layout (e.g. --primary-500, --shadow-2, --max-width). The .container and .question classes define the accordion layout and card appearance. No inline styles or CSS-in-JS in this project.


Reusing Components in Other Projects

Using SingleQuestion elsewhere

  1. Copy SingleQuestion.jsx into your project.
  2. Install react-icons if you use the same icons: npm install react-icons.
  3. Ensure each item has at least title and info (or rename props and adjust JSX).
  4. Reuse the same CSS classes (e.g. .question, .question-btn) or refactor class names and styles to match your design system.

Example in another app:

import SingleQuestion from "./SingleQuestion";

const faqs = [{ id: 1, title: "Your question?", info: "Your answer." }];
// ...
{
  faqs.map((q) => <SingleQuestion key={q.id} {...q} />);
}

Using the whole accordion pattern

  1. Copy App.jsx, Questions.jsx, SingleQuestion.jsx, and data.js.
  2. Replace the contents of data.js with your own array (same shape: id, title, info).
  3. Copy the relevant parts of index.css (e.g. :root variables, .container, .question, .question-btn) into your global or component styles.
  4. If you use a different icon library, replace AiOutlinePlus / AiOutlineMinus and adjust the button content.

“Only one open at a time” (optional enhancement)

Lift state up: in App (or Questions), keep a single state like openId (the id of the open question). Pass openId and setOpenId (or onToggle) to Questions and then to each SingleQuestion. In SingleQuestion, use showInfo = (openId === id) and onClick = () => setOpenId(openId === id ? null : id). That way only one item is expanded at a time.


Functionalities & Features in Detail

Functionality Where it lives How it works
Load questions App.jsx + data.js useState(data); data is static.
Render list Questions.jsx questions.map(...) with key={question.id}.
Expand/collapse SingleQuestion.jsx showInfo state; button toggles it; answer and icon depend on showInfo.
Icons SingleQuestion.jsx react-icons AiOutlinePlus / AiOutlineMinus.
Styling index.css Global and class-based; CSS variables for colors and spacing.
No backend No fetch or env-based API URL; all data from data.js.

Keywords & Learning Outcomes

Concepts:

  • React functional components
  • useState hook
  • Props and unidirectional data flow
  • Conditional rendering
  • Component composition (App → Questions → SingleQuestion)
  • Event handling (onClick)
  • List rendering and key
  • Static data vs. future API integration

Tech:

  • React 18, Vite, JavaScript (ES6+), react-icons, custom CSS

Outcomes:

  • Structure a small React app with clear component boundaries.
  • Manage local UI state (open/closed) inside a repeated component.
  • Use props to pass data from parent to child.
  • Iterate over an array and render a list of components with stable keys.

Conclusion

This Accordion project is a small but complete example of React fundamentals: state, props, conditional rendering, and list rendering. It is suitable for learning, teaching, or as a starting point for FAQ/collapsible UIs. The codebase is intentionally minimal so you can extend it (e.g. “single open only”, API-driven data, or different styling) without changing the core patterns.

For the full code and history, see the GitHub repository.


License

This project is licensed under the MIT License. Feel free to use, modify, and distribute the code as per the terms of the license.

Happy Coding! 🎉

This is an open-source project—feel free to use, enhance, and extend it further!

If you have any questions or want to share your work, reach out via GitHub or my portfolio at https://www.arnobmahmud.com.

Enjoy building and learning! 🚀

Thank you! 😊

About

An interactive React application that demonstrates core React concepts through an Accordion UI—a set of questions with toggleable answers. It is ideal for learners who want to strengthen their understanding of React state management, component structure, event handling, for building FAQ sections, collapsible content or any expand/collapse interface

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors