fix(channels): keep truncated-prompt toggle inline beside the ellipsis#3731
Conversation
The channel feed's ExpandablePrompt rendered the more/less toggle as a sibling below the clamped body, so it always landed on its own line, and whitespace-pre-wrap left the -webkit-line-clamp ellipsis with a leading space (or on a blank line) for multi-line prompts. Move the toggle inside the clamped body, pinned to the bottom-right with a solid background so it sits beside the ellipsis on the last visible line, and switch whitespace to pre-line so trailing spaces collapse against the ellipsis while newlines still break. Generated-By: PostHog Code Task-Id: 21f31a04-8014-4b94-bc8d-2cbc012a70ef
|
😎 Merged successfully - details. |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
✅ Visual changes approved by @adboio — baseline updated in 2 changed. |
The previous attempt pinned the toggle to the bottom-right corner of the clamped block, so it sat at the right edge even when the last line was short, not inline with the ellipsis. Truncate the prompt by hand (no -webkit-line-clamp): measure a hidden copy of the full text and binary-search the longest prefix that still fits in N lines once "...more" is appended, then render that prefix + an inline "more" toggle. The toggle now flows right after the ellipsis on the last visible line, like "...prompt...more". Generated-By: PostHog Code Task-Id: 21f31a04-8014-4b94-bc8d-2cbc012a70ef
2 updated Run: ccb06f1b-36a4-4dcb-9603-16b7bde1b17f Co-authored-by: adboio <23323033+adboio@users.noreply.github.com>
Prompt To Fix All With AIFix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
packages/ui/src/features/canvas/components/ChannelFeedView.tsx:476
**Prompt Updates Keep Stale Cut**
When polling updates a task description without replacing the keyed row, this ref callback does not run again because `children` is not a dependency. If the hidden element's border-box size stays unchanged, `ResizeObserver` also need not fire, so the visible body keeps the previous prompt's cut text until another resize occurs.
```suggestion
[children, expanded, lines],
```
### Issue 2 of 3
packages/ui/src/features/canvas/components/ChannelFeedView.tsx:468
**Zero-Fit State Hides Toggle**
When the available width is too narrow for any prompt character plus `…more`, the search leaves `best` at zero and stores `null`. The render path treats that as an untruncated prompt, but still clips it to the collapsed height and omits the toggle, leaving the hidden text impossible to expand.
### Issue 3 of 3
packages/ui/src/features/canvas/components/ChannelFeedView.tsx:451-454
**Probe Omits Real Button Width**
The search measures plain `more` text using the prompt's inherited typography, while the visible suffix is a `text-xs` button with left padding. When that button is wider than the probe text, the selected prefix no longer fits within the target lines; the button wraps below the clamped height and can be partly or fully clipped.
Reviews (1): Last reviewed commit: "chore(visual): update storybook baseline..." | Re-trigger Greptile |
| observerRef.current = observer; | ||
| }, | ||
| [expanded], | ||
| [expanded, lines], |
There was a problem hiding this comment.
When polling updates a task description without replacing the keyed row, this ref callback does not run again because children is not a dependency. If the hidden element's border-box size stays unchanged, ResizeObserver also need not fire, so the visible body keeps the previous prompt's cut text until another resize occurs.
| [expanded, lines], | |
| [children, expanded, lines], |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/canvas/components/ChannelFeedView.tsx
Line: 476
Comment:
**Prompt Updates Keep Stale Cut**
When polling updates a task description without replacing the keyed row, this ref callback does not run again because `children` is not a dependency. If the hidden element's border-box size stays unchanged, `ResizeObserver` also need not fire, so the visible body keeps the previous prompt's cut text until another resize occurs.
```suggestion
[children, expanded, lines],
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Fixed in 74b9717: children is now the source of truth for the measure text and a dep of the ref callback, so a polled prompt update re-runs the measure even when the rendered size is unchanged.
| } | ||
| } | ||
| text.nodeValue = original; | ||
| setCut(best > 0 ? `${original.slice(0, best).trimEnd()}…` : null); |
There was a problem hiding this comment.
When the available width is too narrow for any prompt character plus …more, the search leaves best at zero and stores null. The render path treats that as an untruncated prompt, but still clips it to the collapsed height and omits the toggle, leaving the hidden text impossible to expand.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/canvas/components/ChannelFeedView.tsx
Line: 468
Comment:
**Zero-Fit State Hides Toggle**
When the available width is too narrow for any prompt character plus `…more`, the search leaves `best` at zero and stores `null`. The render path treats that as an untruncated prompt, but still clips it to the collapsed height and omits the toggle, leaving the hidden text impossible to expand.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Fixed in 74b9717: the cut is now always set when the prompt overflows, so at extreme narrow widths (where no full character fits alongside …more) the toggle still renders and the prompt stays expandable rather than being silently clipped.
| const fits = (end: number) => { | ||
| text.nodeValue = `${original.slice(0, end).trimEnd()}…more`; | ||
| return measure.scrollHeight <= maxHeight + 0.5; | ||
| }; |
There was a problem hiding this comment.
The search measures plain more text using the prompt's inherited typography, while the visible suffix is a text-xs button with left padding. When that button is wider than the probe text, the selected prefix no longer fits within the target lines; the button wraps below the clamped height and can be partly or fully clipped.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/features/canvas/components/ChannelFeedView.tsx
Line: 451-454
Comment:
**Probe Omits Real Button Width**
The search measures plain `more` text using the prompt's inherited typography, while the visible suffix is a `text-xs` button with left padding. When that button is wider than the probe text, the selected prefix no longer fits within the target lines; the button wraps below the clamped height and can be partly or fully clipped.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Verified as a false positive: the more button renders at text-xs (0.75rem), which is narrower than the body-font (0.875rem) probe text — so the probe conservatively over-reserves room for the suffix. Measured directly: the real suffix (ellipsis at 0.875rem + button at 0.75rem with pl-1) is ~49px vs the probe's ~50px, and the real-browser runs across 2-line and 4-line clamps showed the button landing inline (moreRight ≥ 6px) with no overflow/wrap. No change needed.
|
Note 🤖 stamphog reviewed Three unresolved P1 findings from Greptile on the same file (stale cut when props change without remeasure, a zero-fit edge case that hides an unreachable "more" toggle, and a probe that ignores the real button's width/padding) look like genuine correctness bugs in the new binary-search truncation logic, and none are addressed in the diff or discussion.
Gate mechanics and policy version
|
…n overflowing
Address Greptile review comments on ExpandablePrompt:
- "Prompt Updates Keep Stale Cut": use `children` (the prop) as the source
of truth for the measure text and add it to the callback-ref deps, so a
polled prompt update re-runs the measure even when the rendered size is
unchanged (ResizeObserver alone would miss same-size text swaps).
- "Zero-Fit State Hides Toggle": always cut when the prompt overflows, even
when no full character fits alongside "...more" (extreme narrow widths),
so the toggle still renders and the prompt stays expandable instead of
being silently clipped with no way to expand.
The third comment ("Probe Omits Real Button Width") is a false positive: the
text-xs button renders narrower than the body-font probe text, so the probe
conservatively over-reserves room and the button never wraps.
Generated-By: PostHog Code
Task-Id: 21f31a04-8014-4b94-bc8d-2cbc012a70ef
There was a problem hiding this comment.
Pure frontend UI fix (inline "more" toggle placement) in canvas prompt truncation, no risky territory touched. Two substantive Greptile findings were fixed and acknowledged; the remaining unresolved thread is a cosmetic sizing nuance the author rebutted with measurements and the reporting bot 👍'd, not a functional showstopper.
- Author wrote 0% of the modified lines and has 117 merged PRs in these paths (familiarity MODERATE).
- 👍 on the PR from greptile-apps[bot].
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 113L, 2F substantive, 176L/3F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (176L, 3F, two-areas, fix) |
| stamphog 2.0.0b3 | .stamphog/policy.yml @ f377ae9 · reviewed head 74b9711 |
Problem
The channel-feed prompt truncation (added in #3698) had two rough edges: the more/less toggle always sat on its own line below the clamped text, and the -webkit-line-clamp ellipsis picked up a leading space (or landed on a blank line) for multi-line prompts. The toggle should sit inline right after the ellipsis, like "...prompt...more".
Changes
Why: the truncated prompt preview should read as one flowing line ending in "...more", with the toggle clickable right there — not an ellipsis on its own line and a toggle pinned to the block's corner.
How did you test this?
Note: the channels-taskfeedrow--long-prompt visual story snapshots will need regenerating. apps/code/snapshots.yml is maintained by the visual-regression tooling, not test-storybook, so those hashes could not be recomputed here.
Automatic notifications
Created with PostHog Code