From 2b5c6fd606a122229c6346601ebc2b4558a226b7 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 18 Jun 2026 18:33:36 -0400 Subject: [PATCH] perf(media): center-top focal point on cover-fit thumbnails (P5-6) Adds objectPosition:'center top' to all cover-fit thumbnail surfaces so portrait images show faces/subjects instead of the center-slice when the 600px AttachmentBox height cap forces cropping. Co-Authored-By: Claude Sonnet 4.6 --- LOTUS_TODO.md | 5 +++-- src/app/components/RenderMessageContent.tsx | 2 +- src/app/components/media/media.css.ts | 1 + src/app/features/room/MediaGallery.tsx | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/LOTUS_TODO.md b/LOTUS_TODO.md index 020c82cc9..c3f5e8a31 100644 --- a/LOTUS_TODO.md +++ b/LOTUS_TODO.md @@ -283,10 +283,11 @@ Themes: **What:** Use `IntersectionObserver` to trigger media decryption and loading only when components approach the viewport. **Approach:** Reduce initial memory footprint and improve timeline load times by deferring decryption of images/videos until they are visible. -### [ ] P5-6 · Context-Aware Thumbnail Previews +### [x] P5-6 · Context-Aware Thumbnail Previews ⚠️ UNTESTED **What:** Enhance thumbnail rendering in the timeline for consistent, polished aesthetics. -**Approach:** Use CSS `object-fit: cover` with improved focal-point centering within `ThumbnailContent` to prevent media stretching or awkward aspect-ratio cropping. +**Approach:** Use CSS `object-fit: cover` with improved focal-point centering within `ThumbnailContent` to prevent media stretching or awkward aspect-ratio cropping. +**Fix Applied:** Added `objectPosition: 'center top'` to: (1) `media.css.ts` → `Image` component (timeline images), (2) video thumbnail inline style in `RenderMessageContent.tsx`, (3) `GalleryTile` `` in `MediaGallery.tsx`. Full-size viewers retain `objectFit: 'contain'` — no change. `objectPosition: 'center top'` prevents face/subject cropping on tall portrait images capped at 600px by `AttachmentBox`. --- diff --git a/src/app/components/RenderMessageContent.tsx b/src/app/components/RenderMessageContent.tsx index 5033d26ff..772deefa0 100644 --- a/src/app/components/RenderMessageContent.tsx +++ b/src/app/components/RenderMessageContent.tsx @@ -237,7 +237,7 @@ export function RenderMessageContent({ title={body} src={src} loading="lazy" - style={{ objectFit: 'cover', width: '100%', height: '100%' }} + style={{ objectFit: 'cover', objectPosition: 'center top', width: '100%', height: '100%' }} /> )} /> diff --git a/src/app/components/media/media.css.ts b/src/app/components/media/media.css.ts index b563ef3ed..8208ce287 100644 --- a/src/app/components/media/media.css.ts +++ b/src/app/components/media/media.css.ts @@ -5,6 +5,7 @@ export const Image = style([ DefaultReset, { objectFit: 'cover', + objectPosition: 'center top', width: '100%', height: '100%', }, diff --git a/src/app/features/room/MediaGallery.tsx b/src/app/features/room/MediaGallery.tsx index ac4e96478..6bb489c36 100644 --- a/src/app/features/room/MediaGallery.tsx +++ b/src/app/features/room/MediaGallery.tsx @@ -422,7 +422,7 @@ function GalleryTile({ {body} )}