TailwindCSS + React Accordion
Accordion.tsx
import * as React from 'react'
interface AccordionProps {
title: React.ReactNode
children: React.ReactNode
}
const ChevronIcon = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
{...props}
>
<path strokeLinecap="round" strokeLinejoin="round" d="m19 9-7 7-7-7" />
</svg>
)
export const Accordion: React.FC<AccordionProps> = ({ title, children }) => {
const [active, setActive] = React.useState(false)
const [height, setHeight] = React.useState('0px')
const [rotate, setRotate] = React.useState('transform duration-700 ease')
const contentSpace = React.useRef(null)
function toggleAccordion() {
setActive((prevState) => !prevState)
// @ts-ignore
setHeight(active ? '0px' : `${contentSpace.current.scrollHeight}px`)
setRotate(active ? 'transform duration-700 ease' : 'transform duration-700 ease rotate-180')
}
return (
<div className="flex flex-col">
<button
className="py-6 box-border appearance-none cursor-pointer focus:outline-none flex items-center justify-between"
onClick={toggleAccordion}
>
<p className="inline-block text-footnote light">{title}</p>
<ChevronUpIcon
className={`${rotate} inline-block w-6 h-6`} aria-hidden="true"
/>
</button>
<div
ref={contentSpace}
style={{ maxHeight: `${height}` }}
className="overflow-auto transition-max-height duration-700 ease-in-out"
>
{children}
</div>
</div>
)
}
export default Accordion;
How to use
<Accordion title="1">
<div className="pb-5">1 test</div>
</Accordion>
<Accordion title="2">
<div className="pb-5">2 test</div>
</Accordion>