Skip to content

Commit

Permalink
Create a reusable Collapse component
Browse files Browse the repository at this point in the history
  • Loading branch information
widgeter committed Feb 23, 2023
1 parent 3c44ae7 commit 4685090
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 110 deletions.
61 changes: 61 additions & 0 deletions src/components/common/Collapse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';

import { IconChevronDown, IconChevronUp } from '@tabler/icons-react';
import { useState } from 'react';
import { CollapseProps } from '~/shared/types';

const Collapse = ({ items, classCollapseItem }: CollapseProps) => {
const [toggle, setToggle] = useState<boolean>(true);
const [activeIndex, setActiveIndex] = useState<undefined | number>(undefined);

const handleSetIndex = (index: number) => {
if (activeIndex !== index) {
setActiveIndex(index);
setToggle(!toggle);
} else {
setActiveIndex(undefined);
setToggle(!toggle);
}
};

return (
<>
{items.map(({ title, description }, index) => (
<div
key={`accordion-${index}`}
onClick={() => handleSetIndex(index)}
className="mx-auto max-w-3xl select-none bg-transparent text-base text-gray-700"
>
<div className={classCollapseItem}>
<div
className="align-center flex justify-between"
id={`accordion__heading-${index}`}
aria-disabled="false"
aria-expanded="false"
aria-controls={`accordion__panel-${index}`}
role="button"
>
<h2 className="w-full pr-2 text-lg font-medium leading-6 text-gray-900 dark:text-slate-300">{title}</h2>
{activeIndex === index ? (
<IconChevronUp className="h-6 w-6 text-primary-600 dark:text-slate-200" />
) : (
<IconChevronDown className="h-6 w-6 text-primary-600 dark:text-slate-200" />
)}
</div>
{activeIndex === index && (
<div
className="mt-3 select-none"
aria-labelledby={`accordion__heading-${index}`}
id={`accordion__panel-${index}`}
>
<p className="mt-2 text-gray-600 dark:text-slate-400">{description}</p>
</div>
)}
</div>
</div>
))}
</>
);
};

export default Collapse;
58 changes: 5 additions & 53 deletions src/components/widgets/FAQs2.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,18 @@
'use client';

import { useState } from 'react';
import { IconChevronDown, IconChevronUp } from '@tabler/icons-react';
import { faqsData } from '~/shared/data';
import HeaderWidget from '../common/HeaderWidget';
import Collapse from '../common/Collapse';

const FAQs2 = () => {
const { header, items } = faqsData;

const [toggle, setToggle] = useState<boolean>(true);
const [activeIndex, setActiveIndex] = useState<undefined | number>(undefined);

const handleSetIndex = (index: number) => {
if (activeIndex !== index) {
setActiveIndex(index);
setToggle(!toggle);
} else {
setActiveIndex(undefined);
setToggle(!toggle);
}
};

return (
<section id="faqsTwo">
<div className="mx-auto max-w-6xl px-4 py-16 sm:px-6 lg:px-8 lg:py-20">
{header && <HeaderWidget header={header} titleClassname="text-3xl sm:text-4xl" />}
{items.map(({ title, description }, index) => (
<div
key={`accordion-${index}`}
onClick={() => handleSetIndex(index)}
className="mx-auto mb-2 max-w-3xl select-none rounded-md border border-gray-300 bg-transparent px-5 py-4 text-base text-gray-700 shadow-md"
>
<div className="py-1 px-0 md:px-3">
<div
className="align-center flex justify-between"
id={`accordion__heading-${index}`}
aria-disabled="false"
aria-expanded="false"
aria-controls={`accordion__panel-${index}`}
role="button"
>
<h2 className="w-full pr-2 text-lg font-medium leading-6 text-gray-900 dark:text-slate-300">{title}</h2>
<>
{activeIndex === index ? (
<IconChevronUp className="h-6 w-6 text-primary-600 dark:text-slate-200" />
) : (
<IconChevronDown className="h-6 w-6 text-primary-600 dark:text-slate-200" />
)}
</>
</div>
{activeIndex === index && (
<div
className="mt-3 select-none"
aria-labelledby={`accordion__heading-${index}`}
id={`accordion__panel-${index}`}
>
<p className="mt-2 text-gray-600 dark:text-slate-400">{description}</p>
</div>
)}
</div>
</div>
))}
<Collapse
items={items}
classCollapseItem="mb-2 rounded-md border border-gray-300 shadow-md md:px-6 py-4 px-5 md:py-5"
/>
</div>
</section>
);
Expand Down
62 changes: 6 additions & 56 deletions src/components/widgets/FAQs3.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
'use client';

import { useState } from 'react';
import { IconChevronDown, IconChevronUp } from '@tabler/icons-react';
import { faqs3Data } from '~/shared/data';
import HeaderWidget from '../common/HeaderWidget';
import Collapse from '../common/Collapse';

const FAQs3 = () => {
const { header, items, link } = faqs3Data;

const [toggle, setToggle] = useState<boolean>(true);
const [activeIndex, setActiveIndex] = useState<undefined | number>(undefined);

const handleSetIndex = (index: number) => {
if (activeIndex !== index) {
setActiveIndex(index);
setToggle(!toggle);
} else {
setActiveIndex(undefined);
setToggle(!toggle);
}
};

return (
<section className="bg-primary-50 dark:bg-slate-800" id="faqsThree">
<div className="mx-auto max-w-6xl px-4 py-16 sm:px-6 lg:px-8 lg:py-20">
Expand All @@ -36,45 +20,11 @@ const FAQs3 = () => {
)}
</div>
</div>
<div className="mt-4 h-fit md:col-span-2 md:m-4 md:px-4">
{items.map(({ title, description }, index) => (
<div
key={`accordion-${index}`}
onClick={() => handleSetIndex(index)}
className="mx-auto max-w-3xl select-none bg-transparent px-1 pb-4 text-base text-gray-700 md:px-5"
>
<div className="border-b border-solid border-slate-300 pt-1 pb-5 dark:border-slate-500">
<div
className="align-center flex justify-between"
id={`accordion__heading-${index}`}
aria-disabled="false"
aria-expanded="false"
aria-controls={`accordion__panel-${index}`}
role="button"
>
<h2 className="w-full pr-2 text-lg font-medium leading-6 text-gray-900 dark:text-slate-300">
{title}
</h2>
<>
{activeIndex === index ? (
<IconChevronUp className="h-6 w-6 text-primary-600 dark:text-slate-200" />
) : (
<IconChevronDown className="h-6 w-6 text-primary-600 dark:text-slate-200" />
)}
</>
</div>
{activeIndex === index && (
<div
className="mt-3 select-none"
aria-labelledby={`accordion__heading-${index}`}
id={`accordion__panel-${index}`}
>
<p className="mt-2 text-gray-600 dark:text-slate-400">{description}</p>
</div>
)}
</div>
</div>
))}
<div className="mt-4 h-fit md:col-span-2 md:mx-4 md:mt-0 md:px-4">
<Collapse
items={items}
classCollapseItem="border-b border-solid border-slate-300 dark:border-slate-500 py-5"
/>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/widgets/Team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const Team = () => {
href={href}
target="_blank"
rel="noopener noreferrer"
aria-label={title}
aria-label={title as string}
className="flex items-center justify-center rounded-sm bg-transparent p-0.5 text-primary-900 hover:bg-primary-900 hover:text-slate-200 hover:dark:bg-slate-800 hover:dark:text-slate-200"
>
<Icon className="h-6 w-6 p-0.5" />
Expand Down
5 changes: 5 additions & 0 deletions src/shared/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ interface FAQsProps {
link?: Link;
}

interface CollapseProps {
items: Array<Item>;
classCollapseItem?: string;
}

interface CallToActionProps {
title: string;
subtitle: string;
Expand Down

0 comments on commit 4685090

Please sign in to comment.