mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(desktop): more compact "compact" link previews (#5629)
**Category:** improvement **User Impact:** Compact link previews now use a single-line title and smaller thumbnail, making conversations easier to scan. **Problem:** Compact previews gave long titles and oversized thumbnails too much visual weight in the message timeline. **Solution:** Keep titles to one ellipsized line and reduce image thumbnails to a 104×64 treatment while preserving the existing wide aspect ratio; Rich previews remain unchanged. <details> <summary>File changes</summary> **desktop/src/shared/ui/compact-link-preview-attachment.tsx** Tightens the Compact presentation with a single-line title and smaller wide thumbnail, leaving Rich previews untouched. **desktop/tests/e2e/messaging.spec.ts** Adds focused coverage for title overflow, exact 64px card and 104×64 thumbnail geometry, and successful decoded-image rendering using a realistic fixture, plus an optional visual capture. **desktop/tests/fixtures/github-pr-5629-og.png** Provides realistic visible image bytes for the compact-preview image-rendering E2E path. </details> ## Reproduction steps 1. Launch the desktop app with link preview style set to Compact. 2. Send a link whose preview has an image and a long title. 3. Confirm the thumbnail renders at the smaller wide size and the title truncates to one line with an ellipsis. 4. Switch link preview style to Rich and confirm its presentation is unchanged. ## Screenshot  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -79,7 +79,7 @@ export function CompactLinkPreviewAttachment({
|
||||
className={cn(
|
||||
"w-full bg-transparent no-underline shadow-none hover:bg-transparent",
|
||||
reserveImage
|
||||
? "h-21 min-h-21 max-h-21 gap-0 border-0 p-0 hover:border-transparent"
|
||||
? "gap-0 border-0 px-0 py-0 hover:border-transparent"
|
||||
: "rounded-none border-0 border-l-[3px] border-border px-0 py-1 pl-3 hover:border-border",
|
||||
)}
|
||||
data-image-state={preview.imageState}
|
||||
@@ -89,7 +89,7 @@ export function CompactLinkPreviewAttachment({
|
||||
{reserveImage ? (
|
||||
<AttachmentMedia
|
||||
aria-hidden={showImage ? undefined : "true"}
|
||||
className="aspect-auto h-full min-h-0 w-30 min-w-30 max-w-30 self-stretch rounded-xl bg-muted sm:w-34 sm:min-w-34 sm:max-w-34"
|
||||
className="aspect-auto h-16 w-26 rounded-xl bg-muted"
|
||||
data-link-preview-thumbnail=""
|
||||
variant="image"
|
||||
>
|
||||
@@ -110,7 +110,7 @@ export function CompactLinkPreviewAttachment({
|
||||
)}
|
||||
</AttachmentMedia>
|
||||
) : null}
|
||||
<AttachmentContent className={reserveImage ? "px-2 py-2" : undefined}>
|
||||
<AttachmentContent className={reserveImage ? "px-2 py-1.5" : undefined}>
|
||||
<a
|
||||
className="relative z-20 flex w-fit max-w-full min-w-0 items-center gap-1.5 text-xs font-normal leading-4 text-muted-foreground/70 group-hover/attachment:underline"
|
||||
data-link-preview-hostname=""
|
||||
@@ -145,7 +145,7 @@ export function CompactLinkPreviewAttachment({
|
||||
) : null}
|
||||
<span className="truncate">{hostname}</span>
|
||||
</a>
|
||||
<AttachmentTitle className="line-clamp-2 whitespace-normal group-hover/attachment:underline">
|
||||
<AttachmentTitle className="group-hover/attachment:underline">
|
||||
{preview.title}
|
||||
</AttachmentTitle>
|
||||
{preview.description ? (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
import { expect, test, type Locator } from "@playwright/test";
|
||||
|
||||
import { waitForAnimations } from "../helpers/animations";
|
||||
@@ -5,6 +7,11 @@ import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge";
|
||||
import { expectCornerRadiusPx, expectSmoothCorners } from "../helpers/css";
|
||||
import { openSettings } from "../helpers/settings";
|
||||
|
||||
const LINK_PREVIEW_IMAGE = readFileSync(
|
||||
new URL("../fixtures/github-pr-5629-og.png", import.meta.url),
|
||||
);
|
||||
const LINK_PREVIEW_IMAGE_DATA_URL = `data:image/png;base64,${LINK_PREVIEW_IMAGE.toString("base64")}`;
|
||||
|
||||
async function waitForReadyComposerSnapshots(
|
||||
page: import("@playwright/test").Page,
|
||||
count = 1,
|
||||
@@ -208,8 +215,7 @@ test.beforeEach(async ({ page }, testInfo) => {
|
||||
siteName: "GitHub",
|
||||
description:
|
||||
"A polished, stable preview for shared links.",
|
||||
imageDataUrl:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
|
||||
imageDataUrl: LINK_PREVIEW_IMAGE_DATA_URL,
|
||||
imageDomain: "opengraph.githubassets.com",
|
||||
faviconDataUrl:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
|
||||
@@ -1302,6 +1308,55 @@ test("composer link preview embeds stay attachment-sized while loading and ready
|
||||
}
|
||||
});
|
||||
|
||||
test("compact link preview image geometry truncates long titles to one line", async ({
|
||||
page,
|
||||
}) => {
|
||||
const previewUrl = "https://github.com/block/buzz/pull/3246?geometry=1";
|
||||
await page.route("http://localhost:3000/media/*.png", (route) =>
|
||||
route.fulfill({
|
||||
body: LINK_PREVIEW_IMAGE,
|
||||
contentType: "image/png",
|
||||
}),
|
||||
);
|
||||
await page.setViewportSize({ width: 800, height: 700 });
|
||||
await page.goto("/");
|
||||
await page.getByTestId("channel-general").click();
|
||||
await page.getByTestId("message-input").fill(previewUrl);
|
||||
await waitForReadyComposerSnapshots(page);
|
||||
await page.getByTestId("send-message").click();
|
||||
|
||||
const row = page.getByTestId("message-row").last();
|
||||
const card = row.locator('[data-link-preview="github-pull-request"]');
|
||||
const thumbnail = card.locator("[data-link-preview-thumbnail]");
|
||||
const title = card.locator('[data-slot="attachment-title"]');
|
||||
const image = thumbnail.locator("img");
|
||||
await expect(card).toHaveAttribute("data-image-state", "image");
|
||||
await expect(image).toBeVisible();
|
||||
await expect
|
||||
.poll(() => image.evaluate((element) => element.naturalWidth))
|
||||
.toBeGreaterThan(0);
|
||||
await expect(card).toHaveCSS("height", "64px");
|
||||
await expect(thumbnail).toHaveCSS("height", "64px");
|
||||
await expect(thumbnail).toHaveCSS("width", "104px");
|
||||
await expect(title).toHaveText(
|
||||
"Ship a wider horizontal preview with a two-line title that wraps cleanly",
|
||||
);
|
||||
await expect(title).toHaveCSS("white-space", "nowrap");
|
||||
await expect
|
||||
.poll(() =>
|
||||
title.evaluate((element) => element.scrollWidth - element.clientWidth),
|
||||
)
|
||||
.toBeGreaterThan(1);
|
||||
|
||||
if (process.env.BUZZ_LINK_PREVIEW_SCREENSHOTS_DIR) {
|
||||
await waitForAnimations(page);
|
||||
await row.screenshot({
|
||||
animations: "disabled",
|
||||
path: `${process.env.BUZZ_LINK_PREVIEW_SCREENSHOTS_DIR}/recipient-compact-long-title.png`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("composer no-image link embeds keep the attachment footprint", async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Reference in New Issue
Block a user