Skip to content

Commit

Permalink
feat: add accordion to core folder
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandar-r committed Mar 26, 2024
1 parent 1c5142b commit 180490e
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/core/Accordion/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react";
import Accordion, { AccordionProps } from "./component.tsx";

export default {
title: "Components/Accordion",
component: Accordion,
args: {
data: [
{
name: "Item 1",
content: "Content 1",
},
{
name: "Item 2",
content: "Content 2",
},
{
name: "Item 3",
content: "Content 3",
},
{
name: "Item 4",
content: "Content 4",
},
],
autoClose: false,
topBorder: false,
bottomBorder: false,
arrowIcon: false,
},
};

export const Default = {};

export const AutoClose = {
render: (args: AccordionProps) => (
<Accordion data={args.data} autoClose={true} />
),
};
Empty file added src/core/Accordion/component.js
Empty file.
147 changes: 147 additions & 0 deletions src/core/Accordion/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import React, { useState, ReactNode, JSX } from "react";
import Icon from "../Icon/component.tsx";

type AccordionData = {
name: string;
content: ReactNode;
};

type AccordionRowProps = {
bottomBorder: boolean;
topBorder: boolean;
active: boolean;
last: boolean;
name: string;
index;
children: ReactNode;
arrowIcon: boolean;
setActiveIndex: (index: number) => void;
};

export type AccordionProps = {
data: AccordionData[];
arrowIcon?: boolean;
topBorder?: boolean;
bottomBorder?: boolean;
id?: string;
autoClose?: boolean;
};

const AccordionRow = ({
name,
children,
index,
setActiveIndex,
active,
topBorder,
bottomBorder,
last,
arrowIcon,
}: AccordionRowProps) => {
let iconActive: JSX.Element, iconInactive: JSX.Element;
const handleSetIndex = () => {
setActiveIndex(index);
};

if (arrowIcon) {
iconActive = (
<Icon
name="icon-gui-disclosure-arrow"
color="text-dark-grey"
size="1.5rem"
additionalCSS="-rotate-90"
/>
);
iconInactive = (
<Icon
name="icon-gui-disclosure-arrow"
color="text-dark-grey"
size="1.5rem"
additionalCSS="rotate-90"
/>
);
} else {
iconActive = (
<Icon name="icon-gui-minus" color="text-dark-grey" size="1.5rem" />
);
iconInactive = (
<Icon name="icon-gui-plus" color="text-dark-grey" size="1.5rem" />
);
}

return (
<div
className={`border-mid-grey ${last && !bottomBorder ? "" : "border-b"} ${
topBorder ? "border-t" : ""
}`}
>
<button
type="button"
onClick={handleSetIndex}
className={`flex w-full px-0 focus:outline-none py-20`}
>
<span className="ui-text-p1 font-bold text-left mr-8">{name}</span>
<span className="ml-auto">{active ? iconActive : iconInactive}</span>
</button>

<section
className="ui-text-p2 transition-all overflow-hidden"
style={{
maxHeight: active ? "500px" : "0",
paddingBottom: active ? "1.5rem" : "0",
}}
>
{children}
</section>
</div>
);
};

const Accordion = ({
data,
id = "id-accordion",
topBorder,
bottomBorder,
arrowIcon,
autoClose,
}: AccordionProps) => {
const [activeIndexes, setActiveIndexes] = useState([]);

const handleSetIndex = (index: number) => {
const currentIndexIsActive = activeIndexes.includes(index);

if (autoClose) {
setActiveIndexes(currentIndexIsActive ? [] : [index]);
} else {
setActiveIndexes(
currentIndexIsActive
? activeIndexes.filter((i) => i !== index)
: [...activeIndexes, index]
);
}
};

return (
<div className="ui-grid-mx max-w-screen-sm sm:mx-auto" id={id}>
{data.map((item, currentIndex) => {
return (
<AccordionRow
key={item.name}
name={item.name}
arrowIcon={arrowIcon}
index={currentIndex}
last={data.length === currentIndex + 1}
topBorder={topBorder && currentIndex === 0}
bottomBorder={bottomBorder && data.length === currentIndex + 1}
active={activeIndexes.includes(currentIndex)}
setActiveIndex={handleSetIndex}
>
{item.content}
</AccordionRow>
);
})}
</div>
);
};

export default Accordion;

0 comments on commit 180490e

Please sign in to comment.