fix(home): match Figma media pills for latest cards
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 37s
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 37s
- Align latest-update media size pills to the Figma spec: 72x24 pill, black background, 24px gray icon cell, 10px label, and the exact small Figma cloud-download SVG. - For non-document latest cards, remove the duplicate footer download action so media cards only show per-media size/download pills plus the bookmark action, matching the Figma non-document card design. - Keep card heights flexible so content determines the final card height instead of locking to design mock heights.
This commit is contained in:
@@ -147,12 +147,49 @@ function FileCard({ post, att }: { post: Post; att: Attachment }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MediaGrid({ attachments }: { attachments: Attachment[] }) {
|
function PillDownloadIcon() {
|
||||||
const visible = attachments.slice(0, 4);
|
return (
|
||||||
const extra = Math.max(0, attachments.length - visible.length);
|
<svg
|
||||||
if (visible.length <= 1) {
|
width="12"
|
||||||
const src = attachmentPreview(visible[0]);
|
height="10"
|
||||||
return src ? (
|
viewBox="0 0 12 10"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M9.84528 3.61663C9.68928 1.5958 8.02426 0 6.00008 0C4.26863 0 2.78232 1.14503 2.30275 2.81502C0.934727 3.29852 0 4.6181 0 6.10918C0 8.034 1.53816 9.60013 3.42862 9.60013H9.00013C10.6544 9.60013 12.0002 8.22993 12.0002 6.54555C12.0002 5.17142 11.113 3.99191 9.84528 3.61663ZM8.0174 5.98132L6.30309 7.7268C6.21952 7.81189 6.1098 7.85465 6.00008 7.85465C5.89037 7.85465 5.78065 7.81189 5.69708 7.7268L3.98277 5.98132C3.8602 5.85652 3.82334 5.66888 3.88977 5.50568C3.9562 5.34291 4.11263 5.23644 4.28577 5.23644H5.14293V3.49096C5.14293 3.00921 5.52693 2.61822 6.00008 2.61822C6.47323 2.61822 6.85724 3.00921 6.85724 3.49096V5.23644H7.71439C7.88754 5.23644 8.04397 5.34291 8.1104 5.50568C8.17683 5.66888 8.13997 5.85652 8.0174 5.98132Z"
|
||||||
|
fill="#A8A9AE"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MediaSizeChip({ att }: { att: Attachment }) {
|
||||||
|
return (
|
||||||
|
<div className="absolute left-3 top-2.5 z-20 flex h-6 w-[72px] items-center overflow-hidden rounded-full bg-black text-white">
|
||||||
|
<span className="grid h-6 w-6 shrink-0 place-items-center bg-[#545454]">
|
||||||
|
<PillDownloadIcon />
|
||||||
|
</span>
|
||||||
|
<span className="flex h-4 w-12 items-center justify-center text-[10px] font-medium leading-4">
|
||||||
|
{formatBytes(att.sizeBytes)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MediaTile({
|
||||||
|
att,
|
||||||
|
showExtra,
|
||||||
|
}: {
|
||||||
|
att: Attachment;
|
||||||
|
showExtra?: number;
|
||||||
|
}) {
|
||||||
|
const src = attachmentPreview(att);
|
||||||
|
const isVideo = att.kind === "video" || att.mime.startsWith("video/");
|
||||||
|
return (
|
||||||
|
<div className="relative h-full w-full overflow-hidden bg-black">
|
||||||
|
{src ? (
|
||||||
<img
|
<img
|
||||||
src={src}
|
src={src}
|
||||||
alt=""
|
alt=""
|
||||||
@@ -160,44 +197,62 @@ function MediaGrid({ attachments }: { attachments: Attachment[] }) {
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : null}
|
||||||
<div className="h-full w-full bg-black" />
|
<MediaSizeChip att={att} />
|
||||||
|
{isVideo ? (
|
||||||
|
<div className="absolute inset-0 grid place-items-center">
|
||||||
|
<span className="grid h-16 w-16 place-items-center rounded-full bg-black/55 text-white backdrop-blur-sm">
|
||||||
|
<Play className="ml-1 h-8 w-8 fill-current" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{showExtra ? (
|
||||||
|
<div className="absolute inset-0 grid place-items-center bg-black/55 text-[24px] font-bold text-white backdrop-blur-sm">
|
||||||
|
+{showExtra}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MediaGrid({ attachments }: { attachments: Attachment[] }) {
|
||||||
|
const visible = attachments.slice(0, 4);
|
||||||
|
const extra = Math.max(0, attachments.length - visible.length);
|
||||||
|
if (visible.length === 0) return <div className="h-full w-full bg-black" />;
|
||||||
|
if (visible.length === 1) return <MediaTile att={visible[0]} />;
|
||||||
|
if (visible.length === 2) {
|
||||||
|
return (
|
||||||
|
<div className="grid h-full w-full grid-cols-2 gap-0">
|
||||||
|
{visible.map((att) => (
|
||||||
|
<MediaTile key={att.id} att={att} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (visible.length === 3) {
|
||||||
|
return (
|
||||||
|
<div className="grid h-full w-full grid-cols-2 gap-0">
|
||||||
|
<MediaTile att={visible[0]} />
|
||||||
|
<div className="grid h-full grid-rows-2 gap-0">
|
||||||
|
<MediaTile att={visible[1]} />
|
||||||
|
<MediaTile att={visible[2]} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-cols-2 grid-rows-2 gap-0">
|
<div className="grid h-full w-full grid-cols-2 grid-rows-2 gap-0">
|
||||||
{visible.map((att, index) => (
|
{visible.map((att, index) => (
|
||||||
<div key={att.id} className="relative overflow-hidden bg-black">
|
<MediaTile
|
||||||
<img
|
key={att.id}
|
||||||
src={attachmentPreview(att)}
|
att={att}
|
||||||
alt=""
|
showExtra={extra > 0 && index === visible.length - 1 ? extra : 0}
|
||||||
className="h-full w-full object-cover"
|
|
||||||
loading="lazy"
|
|
||||||
decoding="async"
|
|
||||||
/>
|
/>
|
||||||
{extra > 0 && index === visible.length - 1 ? (
|
|
||||||
<div className="absolute inset-0 grid place-items-center bg-black/55 text-[24px] font-bold text-white backdrop-blur-sm">
|
|
||||||
+{extra}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MediaBadge({ att }: { att?: Attachment }) {
|
|
||||||
if (!att) return null;
|
|
||||||
return (
|
|
||||||
<div className="absolute left-3 top-3 z-20 inline-flex h-8 items-center overflow-hidden rounded-full bg-black/75 text-[12px] font-medium text-white shadow-lg backdrop-blur">
|
|
||||||
<span className="grid h-8 w-8 place-items-center rounded-full bg-[#3a3a40]">
|
|
||||||
<DownloadCloudIcon />
|
|
||||||
</span>
|
|
||||||
<span className="px-3">{formatBytes(att.sizeBytes)}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function VisualCard({ post }: { post: Post }) {
|
function VisualCard({ post }: { post: Post }) {
|
||||||
const { lang } = useI18n();
|
const { lang } = useI18n();
|
||||||
const att = post.attachments[0];
|
const att = post.attachments[0];
|
||||||
@@ -213,21 +268,13 @@ function VisualCard({ post }: { post: Post }) {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<MediaGrid attachments={post.attachments} />
|
<MediaGrid attachments={post.attachments} />
|
||||||
<MediaBadge att={att} />
|
|
||||||
{isVideo ? (
|
|
||||||
<div className="absolute inset-0 grid place-items-center">
|
|
||||||
<span className="grid h-14 w-14 place-items-center rounded-full bg-black/55 text-white backdrop-blur-sm">
|
|
||||||
<Play className="ml-1 h-7 w-7 fill-current" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
{text || post.title ? (
|
{text || post.title ? (
|
||||||
<div className="message-stream-copyable-text whitespace-pre-wrap break-words px-4 pt-3 text-[15px] font-medium leading-6 text-white">
|
<div className="message-stream-copyable-text whitespace-pre-wrap break-words px-4 pt-3 text-[15px] font-medium leading-6 text-white">
|
||||||
{autolink(text || post.title || "")}
|
{autolink(text || post.title || "")}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<Footer post={post} attachment={att} />
|
<Footer post={post} />
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user