Files
encoach_frontend/src/components/ExamEditor/Shared/SectionDropdown.tsx

85 lines
2.7 KiB
TypeScript

import React, { useState, ReactNode, useRef, useEffect } from 'react';
import { animated, useSpring } from '@react-spring/web';
interface DropdownProps {
title: ReactNode;
open: boolean;
toggleOpen: () => void;
className: string;
children: ReactNode;
}
// Would be way too messy to add the center the title in the other Dropdown
const SectionDropdown: React.FC<DropdownProps> = ({
title,
open,
className,
children,
toggleOpen
}) => {
const contentRef = useRef<HTMLDivElement>(null);
const [contentHeight, setContentHeight] = useState<number>(0);
useEffect(() => {
let resizeObserver: ResizeObserver | null = null;
if (contentRef.current) {
resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.borderBoxSize && entry.borderBoxSize.length > 0) {
const height = entry.borderBoxSize[0].blockSize;
setContentHeight(height + 0);
} else {
// Fallback for browsers that don't support borderBoxSize
const height = entry.contentRect.height;
setContentHeight(height + 0);
}
}
});
resizeObserver.observe(contentRef.current);
}
return () => {
if (resizeObserver) {
resizeObserver.disconnect();
}
};
}, []);
const springProps = useSpring({
height: open ? contentHeight : 0,
opacity: open ? 1 : 0,
config: { tension: 300, friction: 30 }
});
return (
<div>
<button
onClick={() => toggleOpen()}
className={className}
>
<div className='flex flex-row w-full items-center'>
<p className='flex-grow'>{title}</p>
<svg
className={`w-4 h-4 transform transition-transform ${open ? 'rotate-180' : ''}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
</button>
<animated.div style={springProps} className="overflow-hidden">
<div ref={contentRef}>
{children}
</div>
</animated.div>
</div>
);
};
export default SectionDropdown;