ui enhancements

This commit is contained in:
gosangam
2026-05-31 00:26:05 +05:30
parent dcdd2383c6
commit ec20eb996b
16 changed files with 951 additions and 9317 deletions
+32 -8
View File
@@ -26,7 +26,7 @@
* always visible on touch (mobile).
*/
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { ImageIcon, Trash2 } from "lucide-react";
@@ -248,22 +248,46 @@ function Caption({
expanded: boolean;
onToggle: () => void;
}) {
// Show 3 lines collapsed. The "more" toggle appears only when the text
// is long enough to warrant it (a cheap char-length check beats a
// measure-and-compare pass for our purposes — captions over ~180 chars
// will always overflow 3 lines at the rendered font size).
const longEnough = text.length > 180;
// We clamp to 3 lines collapsed and expose a "More" toggle only when
// the clamp is actually hiding something. A char-length heuristic gets
// this wrong: a 200-char caption can fit cleanly in 3 lines on a wide
// card (no clipping → "More" would be a false promise). Instead measure
// scrollHeight vs clientHeight on the clamped <p>. Once we've observed
// overflow we latch it on so "Show less" stays visible after expansion
// (where scrollHeight would equal clientHeight and we'd otherwise lose
// the way back).
const pRef = useRef<HTMLParagraphElement | null>(null);
const [overflowed, setOverflowed] = useState(false);
useEffect(() => {
if (expanded) return;
const el = pRef.current;
if (!el) return;
const measure = () => {
// Sub-pixel rounding can leave a 1px gap even when content fits;
// require a real difference before flagging overflow.
setOverflowed(el.scrollHeight - el.clientHeight > 1);
};
measure();
const ro = new ResizeObserver(measure);
ro.observe(el);
return () => ro.disconnect();
}, [text, expanded]);
const showToggle = overflowed || expanded;
return (
<div className="text-sm text-foreground leading-relaxed">
<p
ref={pRef}
className={cn(
"font-[family-name:var(--font-title)] break-words",
!expanded && longEnough && "line-clamp-3",
!expanded && "line-clamp-3",
)}
>
“{text}”
</p>
{longEnough ? (
{showToggle ? (
<button
type="button"
onClick={onToggle}