"use client" import React, { useState, useRef, useEffect } from 'react'; import { ChevronDown } from 'lucide-react'; /** * FadePreview — the single shared progressive-disclosure primitive for * long lists/sections: renders children inside a height-clamped wrapper * whose bottom fades out via a CSS mask, with a "Show N more / Show less" * toggle below. * * Extracted from `ReleaseChangelogSection`'s `previewFirst` mode (which * itself unified the investor-update detail page's duplicated * `FadedHighlightSection`). Every fade-preview surface must compose THIS * component — do not re-inline the mask/clamp/toggle trio. * * When `hiddenCount <= 0` the children render unclamped and no toggle * shows (single-entry sections need no disclosure). */ export interface FadePreviewProps { /** How many items are visually hidden while collapsed — drives the * "Show N more" label. Pass `total - visible`; `<= 0` disables the * clamp + fade + toggle entirely. */ hiddenCount: number; /** Collapsed height in px. ~120 shows one changelog entry's title + * the start of its description before the mask kicks in. Callers with * taller rows (e.g. delivery tables) pass a larger value. */ collapsedHeight?: number; /** Reset the expanded state when this value changes — otherwise a * parent that refetches and shrinks the list would leave a stale * "expanded" state and a momentarily-wrong "Show 0 more" button. * Callers typically pass the item count. */ resetKey?: unknown; children: React.ReactNode; } export function FadePreview({ hiddenCount, collapsedHeight = 120, resetKey, children, }: FadePreviewProps) { const [expanded, setExpanded] = useState(false); const contentRef = useRef(null); useEffect(() => { setExpanded(false); }, [resetKey]); const needsFade = hiddenCount > 0; // No disclosure needed → no clamp wrapper at all. (Keeping the wrapper // with a `scrollHeight ?? 2000` max-height would clip tall content on // the first render, before the ref measures.) if (!needsFade) return <>{children}; return (
{children}
); }