44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
|
import { useState, useRef, forwardRef, PropsWithChildren, ForwardedRef, useImperativeHandle } from 'react';
|
||
|
|
||
|
type Properties = {
|
||
|
title: string;
|
||
|
open: boolean;
|
||
|
};
|
||
|
|
||
|
export default forwardRef(function Collapsible(
|
||
|
props: PropsWithChildren<Properties>,
|
||
|
outerRef: ForwardedRef<HTMLDivElement> | undefined
|
||
|
) {
|
||
|
const [opened, setOpened] = useState<boolean>(props.open);
|
||
|
const [previouslyOpened, setPreviouslyOpened] = useState<boolean>(props.open);
|
||
|
|
||
|
const innerRef = useRef<HTMLDivElement | null>(null);
|
||
|
useImperativeHandle(outerRef, () => innerRef.current!, []);
|
||
|
|
||
|
if (props.open !== previouslyOpened) {
|
||
|
setOpened(props.open);
|
||
|
setPreviouslyOpened(props.open);
|
||
|
}
|
||
|
|
||
|
const handleClick = () => {
|
||
|
setOpened(!opened);
|
||
|
if (innerRef && innerRef.current) {
|
||
|
innerRef.current.classList.toggle('hidden');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div>
|
||
|
<div
|
||
|
onClick={handleClick}
|
||
|
className="bg-gray-700 text-white cursor-pointer p-4 w-full border-0 hover:bg-gray-500 h-12 items-center justify-between mt-px text-sm xl:text-base leading:normal"
|
||
|
>
|
||
|
{props.title} <span className="float-right">{opened ? '-' : '+'}</span>
|
||
|
</div>
|
||
|
<div className={`px-2 pt-2 overflow-y-auto bg-white text-sm ${opened ? '' : 'hidden'}`} ref={innerRef}>
|
||
|
{props.children}
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
});
|