mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 09:19:51 +00:00
fix(inbox): reply quote no longer overflows or single-lines (#165)
A long reply quote was forcing the entire 3-panel inbox layout
wider, pushing the contact sidebar off-screen and making the page
horizontally scrollable. Two root causes (both correctly diagnosed
in the issue by @tekrexllp):
1. ReplyQuote applied `truncate` to the preview text, which sets
`white-space: nowrap`. Long previews became one impossibly-wide
line instead of wrapping.
2. The flex chain from MessageBubble outward (MessageActions →
middle-panel wrapper → page) had no `min-w-0` on its flex
children. Default `min-width: auto` means a flex child grows to
its content's natural width, so the long quote propagated all the
way up to the inbox-page flex container and pushed the contact
sidebar past the viewport.
Fix:
- ReplyQuote preview now uses `whitespace-pre-wrap break-words`
instead of `truncate`. The author label stays single-line (it's
a name, ellipsis is right for it). `overflow-hidden` on the
inner text container as belt-and-braces.
- MessageActions' .group/actions wrapper gets `min-w-0` so the
`max-w-[75%]` cap actually holds even with wide content.
- inbox/page.tsx middle-panel wrapper gets `min-w-0` so the
MessageThread can shrink below its natural content width when
the conversation list and contact sidebar are also flexing.
Audited the other 38 `truncate` usages across the codebase —
they're all on intentionally single-line content (contact names,
file paths, last-message previews in lists, headers, node
summaries) where ellipsis is the right behavior. ReplyQuote was
the only multi-line `truncate` misuse.
Reported and diagnosed by @tekrexllp in #165.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1b66431acf
commit
13bafa5747
@ -530,10 +530,16 @@ export default function InboxPage() {
|
|||||||
{/* Center panel: Message thread.
|
{/* Center panel: Message thread.
|
||||||
Hidden on mobile when no conversation is selected so the
|
Hidden on mobile when no conversation is selected so the
|
||||||
list can occupy the full width. Always visible on lg+
|
list can occupy the full width. Always visible on lg+
|
||||||
(shows its own empty-state if no thread is picked yet). */}
|
(shows its own empty-state if no thread is picked yet).
|
||||||
|
|
||||||
|
`min-w-0` is load-bearing: without it, a single wide piece
|
||||||
|
of content inside the thread (long quote preview, very
|
||||||
|
long URL in a message body) forces the flex child past
|
||||||
|
its share and pushes the contact-sidebar panel off-screen
|
||||||
|
on the right. Issue #165. */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full flex-1 lg:flex",
|
"flex h-full min-w-0 flex-1 lg:flex",
|
||||||
hasActiveConv ? "flex" : "hidden lg:flex",
|
hasActiveConv ? "flex" : "hidden lg:flex",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -85,7 +85,12 @@ export function MessageActions({
|
|||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
onBlur={() => setTouchOpen(false)}
|
onBlur={() => setTouchOpen(false)}
|
||||||
>
|
>
|
||||||
<div className="group/actions relative max-w-[75%]">
|
{/* `min-w-0` lets this flex child actually respect the 75% cap.
|
||||||
|
* Default `min-width: auto` lets content (a long quote preview,
|
||||||
|
* an unbroken URL) push past the cap and shove the row past
|
||||||
|
* 100%, which used to bleed across into the contact-sidebar
|
||||||
|
* area. See issue #165. */}
|
||||||
|
<div className="group/actions relative min-w-0 max-w-[75%]">
|
||||||
{children}
|
{children}
|
||||||
<div
|
<div
|
||||||
data-touch-open={touchOpen || pickerOpen ? "true" : undefined}
|
data-touch-open={touchOpen || pickerOpen ? "true" : undefined}
|
||||||
|
|||||||
@ -31,11 +31,20 @@ export function ReplyQuote({
|
|||||||
: "mb-1.5 rounded-md bg-black/20",
|
: "mb-1.5 rounded-md bg-black/20",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1 overflow-hidden">
|
||||||
<div className="truncate text-[11px] font-medium text-primary">
|
<div className="truncate text-[11px] font-medium text-primary">
|
||||||
{authorLabel}
|
{authorLabel}
|
||||||
</div>
|
</div>
|
||||||
<div className="truncate text-xs text-slate-200/80">{preview}</div>
|
{/* Wrap the preview instead of truncating to a single line.
|
||||||
|
* `truncate` (white-space: nowrap) forced the quote onto one
|
||||||
|
* impossibly-wide line and — because the parent flex chain
|
||||||
|
* lacked `min-w-0` at every step — pushed the entire inbox
|
||||||
|
* layout wider, shoving the contact sidebar off-screen.
|
||||||
|
* `break-words` also wraps long URLs that have no whitespace
|
||||||
|
* to break on. Issue #165. */}
|
||||||
|
<div className="whitespace-pre-wrap break-words text-xs text-slate-200/80">
|
||||||
|
{preview}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{onDismiss && (
|
{onDismiss && (
|
||||||
<button
|
<button
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user