Skip to content

Instantly share code, notes, and snippets.

@mustafadalga
Created October 28, 2025 07:30
Show Gist options
  • Select an option

  • Save mustafadalga/e133b9d6077954d1d9a19854defd160f to your computer and use it in GitHub Desktop.

Select an option

Save mustafadalga/e133b9d6077954d1d9a19854defd160f to your computer and use it in GitHub Desktop.
React Accordion with Smooth Transition
import { useEffect, useRef, useState } from "react";
const list = [
{
id: "1",
title: "HTML",
context: "The HyperText Markup Language or HTML is the standard markup language for documents designed to be displayed in a web browser."
},
{
id: "2",
title: "CSS",
context: "Cascading Style Sheets is a style sheet language used for describing the presentation of a document written in a markup language such as HTML or XML."
},
{
id: "3",
title: "JavaScript",
context: "JavaScript, often abbreviated as JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS."
}
]
export function Accordion() {
const [ accordion, setAccordion ] = useState<string[]>(list.map(item => item.id))
console.log(accordion)
const toggle = (id: string) => {
setAccordion(prev => {
if (prev.includes(id)) {
return prev.filter(row => row != id)
}
return [ ...prev, id ]
})
}
return (
<div>
{list.map(item => <AccordionItem key={item.id}
item={item}
isOpen={accordion.includes(item.id)}
toggle={toggle}/>)}
</div>
);
}
function AccordionItem({ item, isOpen, toggle }) {
const contentRef = useRef<HTMLDivElement>(null);
const [ height, setHeight ] = useState(0)
console.log(contentRef.current?.scrollHeight)
useEffect(() => {
if (contentRef.current) {
setHeight(contentRef.current.scrollHeight)
}
}, [])
useEffect(() => {
if (contentRef.current) {
setHeight(isOpen ? contentRef.current?.scrollHeight : 0)
}
}, [ isOpen ])
return (
<div>
<div
onClick={() => toggle(item.id)}
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
{item.title}
<span
style={{
display: 'inline-block',
marginLeft: '0.5rem',
transition: 'transform 0.3s',
transform: isOpen ? 'rotate(90deg)' : 'rotate(0deg)',
}}
>
</span>
</div>
<div
style={{
overflow: 'hidden',
transition: 'all 0.3s ease-in',
height,
}}
ref={contentRef}
>
<div style={{ padding: '0.5rem' }}>{item.context}</div>
</div>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment