From 47f8ad4df7004b488fd20140f4ff41ce7f0f2dd5 Mon Sep 17 00:00:00 2001 From: bowenliang123 Date: Tue, 13 Oct 2026 21:47:30 +0800 Subject: [PATCH] style(client): put the preview invite over the thumbnail, not in the card facts The invite as an extra meta row read as clutter and grew the card on hover. It now covers the attachment's 64px thumbnail (a dimmed mask with the label centered), so the facts beside it never move, a long English label wraps inside the tile, and keyboard focus shows it too. --- src/client/components/attachments.tsx | 43 +++++++++++++-------------- src/client/styles/attachments.css | 6 ++-- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/client/components/attachments.tsx b/src/client/components/attachments.tsx index 34e7668..26b0b86 100644 --- a/src/client/components/attachments.tsx +++ b/src/client/components/attachments.tsx @@ -127,24 +127,26 @@ function AttachmentCard(props: { data-state={state} onClick={props.onOpen} > - {image - ? ( - - {thumb.src !== null - ? {name} - : ( - - {thumb.failed ? '⚠' : load === undefined ? '🖼' : t('attach.loading')} - - )} - - ) - : ( - - - {typeOf(attachment, t)} - - )} + + {image + ? thumb.src !== null + ? {name} + : ( + + {thumb.failed ? '⚠' : load === undefined ? '🖼' : t('attach.loading')} + + ) + : ( + <> + + {typeOf(attachment, t)} + + )} + {/* The invite rides the thumbnail: the facts below never move, and nothing wraps around it. */} + + {state === 'opening' ? t('attach.loading') : hint} + + {name} {t('attach.type')}{typeOf(attachment, t)} @@ -154,11 +156,6 @@ function AttachmentCard(props: { ))} {state === 'failed' ? {t('attach.unavailable')} : null} - {state === 'failed' ? null : ( - - {state === 'opening' ? t('attach.loading') : hint} - - )} ) diff --git a/src/client/styles/attachments.css b/src/client/styles/attachments.css index d9e31ed..6436b8c 100644 --- a/src/client/styles/attachments.css +++ b/src/client/styles/attachments.css @@ -17,9 +17,9 @@ .lc-att-row-label { display: inline-block; min-width: 3.2em; font-weight: 400; } /* A refused open reports on its own card — the click never lands anywhere else. */ .lc-att-fail { font-size: 11px; color: var(--dsw-alias-state-error-primary, var(--dsw-alias-label-secondary)); } -/* The preview invite is a normal meta row: it fades in on hover/focus, so it never paints over the - name and the card never changes height when it appears. */ -.lc-att-hint { font-size: 11px; color: var(--dsw-alias-label-secondary); opacity: 0; transition: opacity var(--ds-transition-duration, 0.2s) var(--ds-ease-in-out, ease-in-out); } +/* The preview invite covers the thumbnail on hover/focus: the facts beside it never move, and the + label wraps inside the 64px tile instead of widening the card. */ +.lc-att-hint { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; padding: 2px; box-sizing: border-box; background: var(--dsw-alias-bg-mask-1, rgba(0, 0, 0, 0.45)); color: var(--dsw-alias-label-primary-foreground, #fff); font-size: 10px; line-height: 1.25; text-align: center; overflow-wrap: anywhere; opacity: 0; transition: opacity var(--ds-transition-duration, 0.2s) var(--ds-ease-in-out, ease-in-out); pointer-events: none; } .lc-att-item:hover .lc-att-hint, .lc-att-item:focus-visible .lc-att-hint, .lc-att-hint-on { opacity: 1; } /* Under width pressure the two-column grid folds to one column (a thumbnail plus its facts needs ~240px). */