Spaces:
Build error
Build error
File size: 1,826 Bytes
75fefa7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | "use client";
import React, { useRef, useEffect, ReactNode, useState } from "react";
// Smoothly animates its container to match the natural height of its content.
// Fixes previous behavior where the component observed itself, causing height 0
// with overflow hidden (content clipped) or visible overflow that overlapped
// following sections like the footer.
export default function AnimatedHeight({
children,
overflow = true,
}: {
children: ReactNode;
overflow?: boolean;
}) {
const containerRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const [measuredHeight, setMeasuredHeight] = useState<number | null>(null);
const hasAnimatedOnceRef = useRef(false);
useEffect(() => {
const contentEl = contentRef.current;
const containerEl = containerRef.current;
if (!contentEl || !containerEl) return;
const updateHeight = () => {
// Use scrollHeight to capture full natural height, including overflowed content
const height = contentEl.scrollHeight;
setMeasuredHeight((prev) => (prev === height ? prev : height));
// Enable transition after the first measurement to avoid initial jank
if (!hasAnimatedOnceRef.current) {
containerEl.style.transition = "height 300ms ease-in-out";
hasAnimatedOnceRef.current = true;
}
};
// Initial measure
updateHeight();
const resizeObserver = new ResizeObserver(() => updateHeight());
resizeObserver.observe(contentEl);
return () => resizeObserver.disconnect();
}, []);
return (
<div
ref={containerRef}
style={{
overflow: overflow ? "hidden" : "visible",
height: measuredHeight === null ? undefined : `${measuredHeight}px`,
}}
>
<div ref={contentRef}>{children}</div>
</div>
);
}
|