fix(desktop): restore approved compact preview layout

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w
2026-07-30 23:21:04 -07:00
co-authored by Taylor Ho
parent b3c2ea5ba5
commit 2c5b232cbd
2 changed files with 63 additions and 10 deletions
@@ -6,6 +6,7 @@ import { Button } from "@/shared/ui/button";
import {
Attachment,
AttachmentContent,
AttachmentDescription,
AttachmentMedia,
AttachmentTitle,
AttachmentTrigger,
@@ -142,11 +143,15 @@ export function LinkPreviewAttachment({
}) {
const reserveImage = preview.imageState !== "none";
const showImage = preview.imageState === "image";
const hostname = getHostname(preview);
return (
<div className={cn("relative w-80 max-w-full shrink-0", className)}>
<div className={cn("relative w-[22.5rem] max-w-full shrink-0", className)}>
<Attachment
className="w-full no-underline shadow-none"
className={cn(
"w-full no-underline shadow-none",
reserveImage && "h-20 min-h-20 max-h-20 gap-0 p-0",
)}
data-image-state={preview.imageState}
data-link-preview={preview.kind}
orientation="horizontal"
@@ -154,7 +159,7 @@ export function LinkPreviewAttachment({
{reserveImage ? (
<AttachmentMedia
aria-hidden={showImage ? undefined : "true"}
className="h-12 w-16 rounded-lg bg-muted sm:h-14 sm:w-[6.6875rem]"
className="aspect-auto h-full min-h-0 w-28 min-w-28 max-w-28 self-stretch rounded-none bg-muted sm:w-32 sm:min-w-32 sm:max-w-32"
data-link-preview-thumbnail=""
variant="image"
>
@@ -176,14 +181,27 @@ export function LinkPreviewAttachment({
<LinkPreviewLogo preview={preview} />
</AttachmentMedia>
)}
<AttachmentContent>
<AttachmentContent className={reserveImage ? "px-3 py-2.5" : undefined}>
<div
className="truncate text-xs font-medium leading-4 text-muted-foreground"
className="truncate text-xs font-normal leading-4 text-muted-foreground"
data-link-preview-hostname=""
>
{getHostname(preview)}
{reserveImage ? hostname : preview.provider}
</div>
<AttachmentTitle>{preview.title}</AttachmentTitle>
<AttachmentTitle
className={
reserveImage
? preview.description
? "truncate"
: "line-clamp-2 whitespace-normal"
: undefined
}
>
{preview.title}
</AttachmentTitle>
{reserveImage && preview.description ? (
<AttachmentDescription>{preview.description}</AttachmentDescription>
) : null}
</AttachmentContent>
<AttachmentTrigger asChild>
<a
+38 -3
View File
@@ -310,7 +310,9 @@ test("link preview image geometry stays stable while loading", async ({
await page.goto("/");
await page.getByTestId("channel-general").click();
await page.setViewportSize({ width, height: 700 });
await page.getByTestId("message-input").fill(previewUrl);
await page
.getByTestId("message-input")
.fill(`${previewUrl}?viewport=${width}`);
await page.getByTestId("send-message").click();
const card = page
@@ -328,9 +330,23 @@ test("link preview image geometry stays stable while loading", async ({
}
const pending = await card.evaluate((element) => ({
height: element.getBoundingClientRect().height,
width: element.getBoundingClientRect().width,
textLeft: element
.querySelector('[data-slot="attachment-content"]')
?.getBoundingClientRect().left,
textInset: (() => {
const content = element.querySelector("[data-link-preview-hostname]");
const thumbnail = element.querySelector(
"[data-link-preview-thumbnail]",
);
return content && thumbnail
? content.getBoundingClientRect().left -
thumbnail.getBoundingClientRect().right
: undefined;
})(),
thumbnailHeight: element
.querySelector("[data-link-preview-thumbnail]")
?.getBoundingClientRect().height,
thumbnailWidth: element
.querySelector("[data-link-preview-thumbnail]")
?.getBoundingClientRect().width,
@@ -344,19 +360,35 @@ test("link preview image geometry stays stable while loading", async ({
});
}
const loaded = await card.evaluate((element) => ({
description: element.querySelector('[data-slot="attachment-description"]')
?.textContent,
height: element.getBoundingClientRect().height,
titleClass: element.querySelector('[data-slot="attachment-title"]')
?.className,
textLeft: element
.querySelector('[data-slot="attachment-content"]')
?.getBoundingClientRect().left,
thumbnailHeight: element
.querySelector("[data-link-preview-thumbnail]")
?.getBoundingClientRect().height,
thumbnailWidth: element
.querySelector("[data-link-preview-thumbnail]")
?.getBoundingClientRect().width,
}));
expect(pending.width).toBe(width < 640 ? 325 : 360);
expect(pending.height).toBe(80);
expect(pending.textInset).toBe(12);
expect(pending.thumbnailHeight).toBe(78);
expect(loaded.height).toBe(pending.height);
expect(loaded.textLeft).toBe(pending.textLeft);
expect(loaded.thumbnailHeight).toBe(pending.thumbnailHeight);
expect(loaded.thumbnailWidth).toBe(pending.thumbnailWidth);
expect(loaded.thumbnailWidth).toBe(width < 640 ? 64 : 107);
expect(loaded.thumbnailWidth).toBe(width < 640 ? 112 : 128);
expect(loaded.titleClass).toContain("truncate");
expect(loaded.description).toBe(
"A polished, stable preview for shared links.",
);
}
});
@@ -370,7 +402,9 @@ test("link preview no-image collapse restores the compact card", async ({
await page.goto("/");
await page.getByTestId("channel-general").click();
await page.setViewportSize({ width, height: 700 });
await page.getByTestId("message-input").fill(previewUrl);
await page
.getByTestId("message-input")
.fill(`${previewUrl}&viewport=${width}`);
await page.getByTestId("send-message").click();
const card = page
@@ -378,6 +412,7 @@ test("link preview no-image collapse restores the compact card", async ({
.last()
.locator('[data-link-preview="github-pull-request"]');
await expect(card).toHaveAttribute("data-image-state", "pending");
await expect(card).toBeVisible();
const pending = await card.evaluate((element) => ({
height: element.getBoundingClientRect().height,
textLeft: element