Accordion

Classic + open more than one React JS
import React, { useState } from "react";
import "./styles.css";
const App = () => {
const [expandedAccordion, setExpandedAccordion] = useState({});
const [multiple, setMultiple] = useState(false);
const toggleAccordion = (index) => {
if (!multiple) {
setExpandedAccordion((prevState) => ({
...Object.keys(prevState).reduce((acc, key) => {
acc[key] = false;
return acc;
}, {}),
[index]: !prevState[index],
}));
} else {
setExpandedAccordion((prevState) => ({
...prevState,
[index]: !prevState[index],
}));
}
};
return (
<main className="position-relative">
<div className="multi-select">
<label>
<input
type="checkbox"
className="checkbox"
id="multiselect"
data-testid="multiselect"
onChange={() => setMultiple(!multiple)}
/>
Select Multiple
</label>
</div>
<div className="carousel-container">
<h1 className="accordion-title">Book Collection</h1>
{accordionData.map((item, index) => (
<div className="accordion" data-testid={index + 1} key={index}>
<div
className="title-section"
role="button"
tabIndex={0}
aria-controls={`desc-${index + 1}`}
id={`btn-${index + 1}`}
onClick={() => toggleAccordion(index + 1)}
>
<div className="title">{item.title}</div>
<div
className={`expand-icon ${
expandedAccordion[index + 1] ? "hide" : ""
}`}
></div>
<div
className={`collapse-icon ${
expandedAccordion[index + 1] ? "" : "hide"
}`}
></div>
</div>
<div
className="description"
id={`desc-${index + 1}`}
role="region"
aria-labelledby={`btn-${index + 1}`}
style={{
display: expandedAccordion[index + 1] ? "block" : "none",
}}
>
{item.description}
</div>
</div>
))}
</div>
</main>
);
};
const accordionData = [
{
title: "Mastering Web Design with HTML5 and CSS3",
description:
"Explore the latest HTML5 and CSS3 techniques to create responsive and adaptive web designs that work seamlessly across devices. Learn about CSS Grid, Flexbox, and other modern web tools.",
},
{
title: "The Ultimate Guide to Front-End Development",
description:
"Dive deep into front-end development strategies, tools, and best practices. Learn how to enhance user experience, streamline development processes, and stay ahead in the rapidly evolving web landscape.",
},
{
title: "Interactive Web Development with JavaScript and jQuery",
description:
"Learn how to create dynamic and interactive web applications using JavaScript and jQuery. This guide covers everything from basic syntax to advanced scripting techniques.",
},
{
title: "Innovative Approaches to Product Design",
description:
"This book presents a unique model for the design process, integrating cognitive psychology and engineering principles. Discover how to navigate the early stages of product development with creativity and precision.",
},
{
title: "HTML Essentials",
description:
"A foundational guide to HTML, covering the essential tags and structures needed to build modern web pages. Perfect for beginners and those looking to solidify their knowledge of web development basics.",
},
];
export default App;
Classic + open more than one React TS
import React, { useState } from "react";
import "./styles.css";
interface AccordionItem {
title: string;
description: string;
}
const accordionData: AccordionItem[] = [
{
title: "Mastering Web Design with HTML5 and CSS3",
description:
"Explore the latest HTML5 and CSS3 techniques to create responsive and adaptive web designs that work seamlessly across devices. Learn about CSS Grid, Flexbox, and other modern web tools.",
},
{
title: "The Ultimate Guide to Front-End Development",
description:
"Dive deep into front-end development strategies, tools, and best practices. Learn how to enhance user experience, streamline development processes, and stay ahead in the rapidly evolving web landscape.",
},
{
title: "Interactive Web Development with JavaScript and jQuery",
description:
"Learn how to create dynamic and interactive web applications using JavaScript and jQuery. This guide covers everything from basic syntax to advanced scripting techniques.",
},
{
title: "Innovative Approaches to Product Design",
description:
"This book presents a unique model for the design process, integrating cognitive psychology and engineering principles. Discover how to navigate the early stages of product development with creativity and precision.",
},
{
title: "HTML Essentials",
description:
"A foundational guide to HTML, covering the essential tags and structures needed to build modern web pages. Perfect for beginners and those looking to solidify their knowledge of web development basics.",
},
];
const App: React.FC = () => {
const [expandedAccordion, setExpandedAccordion] = useState<{
[key: number]: boolean;
}>({});
const [multiple, setMultiple] = useState<boolean>(false);
const toggleAccordion = (index: number) => {
if (!multiple) {
setExpandedAccordion((prevState) => ({
...Object.keys(prevState).reduce(
(acc, key) => {
acc[parseInt(key)] = false;
return acc;
},
{} as { [key: number]: boolean },
),
[index]: !prevState[index],
}));
} else {
setExpandedAccordion((prevState) => ({
...prevState,
[index]: !prevState[index],
}));
}
};
return (
<main className="position-relative">
<div className="multi-select">
<label>
<input
type="checkbox"
className="checkbox"
id="multiselect"
data-testid="multiselect"
onChange={() => setMultiple(!multiple)}
/>
Select Multiple
</label>
</div>
<div className="carousel-container">
<h1 className="accordion-title">Book Collection</h1>
{accordionData.map((item, index) => (
<div className="accordion" data-testid={index + 1} key={index}>
<div
className="title-section"
role="button"
tabIndex={0}
aria-controls={`desc-${index + 1}`}
id={`btn-${index + 1}`}
onClick={() => toggleAccordion(index + 1)}
>
<div className="title">{item.title}</div>
<div
className={`expand-icon ${
expandedAccordion[index + 1] ? "hide" : ""
}`}
></div>
<div
className={`collapse-icon ${
expandedAccordion[index + 1] ? "" : "hide"
}`}
></div>
</div>
<div
className="description"
id={`desc-${index + 1}`}
role="region"
aria-labelledby={`btn-${index + 1}`}
style={{
display: expandedAccordion[index + 1] ? "block" : "none",
}}
>
{item.description}
</div>
</div>
))}
</div>
</main>
);
};
export default App;

React JS
import { useState } from "react";
import "./styles.css";
const faqs = [
{
title: "Where are these chairs assembled?",
text: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusantium, quaerat temporibus quas dolore provident nisi ut aliquid ratione beatae sequi aspernatur veniam repellendus.",
},
{
title: "How long do I have to return my chair?",
text: "Pariatur recusandae dignissimos fuga voluptas unde optio nesciunt commodi beatae, explicabo natus.",
},
{
title: "Do you ship to countries outside the EU?",
text: "Excepturi velit laborum, perspiciatis nemo perferendis reiciendis aliquam possimus dolor sed! Dolore laborum ducimus veritatis facere molestias!",
},
];
export default function App() {
return (
<div>
<Accordion data={faqs} />
</div>
);
}
function Accordion({ data }) {
const [curOpen, setCurOpen] = useState(null);
return (
<div className="accordion">
{data.map((el, i) => (
<AccordionItem
curOpen={curOpen}
onOpen={setCurOpen}
title={el.title}
num={i}
key={el.title}
>
{el.text}
</AccordionItem>
))}
<AccordionItem
curOpen={curOpen}
onOpen={setCurOpen}
title="Test 1"
num={22}
key="test 1"
>
<p>Allows React developers to:</p>
<ul>
<li>Break up UI into components</li>
<li>Make components reusuable</li>
<li>Place state efficiently</li>
</ul>
</AccordionItem>
</div>
);
}
function AccordionItem({ num, title, curOpen, onOpen, children }) {
const isOpen = num === curOpen;
function handleToggle() {
onOpen(isOpen ? null : num);
}
return (
<div className={`item ${isOpen ? "open" : ""}`} onClick={handleToggle}>
<p className="number">{num < 9 ? `0${num + 1}` : num + 1}</p>
<p className="title">{title}</p>
<p className="icon">{isOpen ? "-" : "+"}</p>
{isOpen && <div className="content-box">{children}</div>}
</div>
);
}
React TS
import { useState } from "react";
import "./styles.css";
interface FAQ {
title: string;
text: string;
}
interface AccordionProps {
data: FAQ[];
}
interface AccordionItemProps {
num: number;
title: string;
curOpen: number | null;
onOpen: (num: number | null) => void;
children: React.ReactNode;
}
const faqs: FAQ[] = [
{
title: "Where are these chairs assembled?",
text: "Lorem ipsum dolor sit amet consectetur, adipisicing elit. Accusantium, quaerat temporibus quas dolore provident nisi ut aliquid ratione beatae sequi aspernatur veniam repellendus.",
},
{
title: "How long do I have to return my chair?",
text: "Pariatur recusandae dignissimos fuga voluptas unde optio nesciunt commodi beatae, explicabo natus.",
},
{
title: "Do you ship to countries outside the EU?",
text: "Excepturi velit laborum, perspiciatis nemo perferendis reiciendis aliquam possimus dolor sed! Dolore laborum ducimus veritatis facere molestias!",
},
];
export default function App() {
return (
<div>
<Accordion data={faqs} />
</div>
);
}
function Accordion({ data }: AccordionProps) {
const [curOpen, setCurOpen] = useState<number | null>(null);
return (
<div className="accordion">
{data.map((el, i) => (
<AccordionItem
curOpen={curOpen}
onOpen={setCurOpen}
title={el.title}
num={i}
key={el.title}
>
{el.text}
</AccordionItem>
))}
<AccordionItem
curOpen={curOpen}
onOpen={setCurOpen}
title="Test 1"
num={22}
key="test 1"
>
<p>Allows React developers to:</p>
<ul>
<li>Break up UI into components</li>
<li>Make components reusuable</li>
<li>Place state efficiently</li>
</ul>
</AccordionItem>
</div>
);
}
function AccordionItem({
num,
title,
curOpen,
onOpen,
children,
}: AccordionItemProps) {
const isOpen = num === curOpen;
function handleToggle() {
onOpen(isOpen ? null : num);
}
return (
<div className={`item ${isOpen ? "open" : ""}`} onClick={handleToggle}>
<p className="number">{num < 9 ? `0${num + 1}` : num + 1}</p>
<p className="title">{title}</p>
<p className="icon">{isOpen ? "-" : "+"}</p>
{isOpen && <div className="content-box">{children}</div>}
</div>
);
}