mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 01:35:39 -04:00
- Stack title-hero poster/metadata vertically on mobile (flex-col md:flex-row), switch backdrop tall breakpoint from sm to md - Extract bio expand/collapse logic into reusable ExpandableText component; use it in PersonHero and TitleHero - Fix ContinueWatchingCard image to use fill + sizes instead of fixed width/height to avoid layout shift - Add fade-out gradient on genre chip scrollbar edge on mobile - Show scaled-down ambient glow on mobile instead of hiding it entirely - Humanize knownForDepartment labels (Acting→Actor, Directing→Director, etc.) - Change cast member name from truncate to line-clamp-2 for wrapping - Hide tooltip arrow via [&>:last-child]:hidden instead of color-matching it - Apply safe-area-inset padding to HeroBanner content on notched devices
58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface ExpandableTextProps {
|
|
text: string;
|
|
/** Tailwind line-clamp class applied when collapsed (default: "line-clamp-3") */
|
|
clampClass?: string;
|
|
className?: string;
|
|
textClassName?: string;
|
|
}
|
|
|
|
export function ExpandableText({
|
|
text,
|
|
clampClass = "line-clamp-3",
|
|
className,
|
|
textClassName,
|
|
}: ExpandableTextProps) {
|
|
const [expanded, setExpanded] = useState(false);
|
|
const [clamped, setClamped] = useState(false);
|
|
const ref = useRef<HTMLParagraphElement>(null);
|
|
|
|
useEffect(() => {
|
|
const el = ref.current;
|
|
if (!el) return;
|
|
const check = () => setClamped(el.scrollHeight > el.clientHeight + 1);
|
|
check();
|
|
const observer = new ResizeObserver(check);
|
|
observer.observe(el);
|
|
return () => observer.disconnect();
|
|
}, []);
|
|
|
|
return (
|
|
<div className={className}>
|
|
<p
|
|
ref={ref}
|
|
className={cn(
|
|
"break-words text-muted-foreground leading-relaxed",
|
|
!expanded && clampClass,
|
|
textClassName,
|
|
)}
|
|
>
|
|
{text}
|
|
</p>
|
|
{(clamped || expanded) && (
|
|
<button
|
|
type="button"
|
|
onClick={() => setExpanded(!expanded)}
|
|
className="mt-1 font-medium text-primary text-xs transition-colors hover:text-primary/80"
|
|
>
|
|
{expanded ? "Show less" : "Read more"}
|
|
</button>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|