Files
openclaw/ui
Vyctor H. Brzezowski f38a2f51b3 fix(ui): keep chat file links whole when a line wraps (#123310)
* fix(ui): keep chat file links whole when a line wraps

A file reference in chat prose could end a line on its file-type glyph and strand its label on the next line, splitting one reference into two fragments. The chip is now an atomic inline, so it moves to the next line whole, and it is capped at the column width so an unshortened label wraps inside the chip instead of overflowing the bubble.

Closes #123309

* fix(ui): keep the file-link glyph attached to its label on wrap

The prior fix (display: inline-block + max-width: 100% on the anchor)
stopped the whole chip from splitting across the parent's lines, but
left the glyph itself splittable from its label: the ::before glyph
was display: inline-block, an atomic inline with its own contingent
line-break opportunity, so when a long/unbreakable label couldn't fit
next to it, the UA pushed the whole label onto the next line instead
of letting overflow-wrap continue the run — stranding the glyph alone
above it. Switching the glyph to display: inline (sized via
padding-inline-start + an explicit mask size instead of width/height +
contain) removes that break opportunity; the glyph and the label's
first character now share one unbreakable run, while the rest of a
long label still wraps normally via the inherited
overflow-wrap: anywhere.

The existing wrap test couldn't have caught this: a.markdown-file-link
is inline-block, so its own getClientRects() always reports exactly
one rect regardless of how the content wraps inside it. Added a
table-driven probe (short basename, an unbroken long basename with no
natural break points, and a path with a :line suffix) that compares
the chip's own top against its first character's top via a Range,
which does see the internal split. It fails on the pre-fix CSS and
passes after.

* fix(ui): let the wrap probe infer its page.evaluate types

A single explicit type argument on page.evaluate binds Arg to void, so the
sweep's case ids arrived untyped and the shard failed to compile. Inference
reads both the argument and the result from the call.

Also condenses the layout-invariant comments on the file-link rules and the
probe to three lines each.

* test(ui): sweep the glyph probe over enormous and non-ASCII labels

A 240-character basename with no separator and a CJK label reached through a
host-local href both wrap several times inside the chip, so the first cut is
where a glyph would strand. Both fail on the pre-fix rule.

* fix(ui): give the file-link chip its own wrap policy

The atomic chip capped its box with max-width but relied on .chat-text for
overflow-wrap: anywhere. .sidebar-markdown declares no wrapping policy, so in
the Chat Detail Panel an unbreakable label painted past the capped box and the
panel's hidden horizontal overflow clipped it.

Declare the wrap policy on the shared file-link owner and sweep both renderers
in the browser probe: the separation cases now assert the painted label never
runs past the column's content edge.
2026-08-16 00:37:47 -03:00
..