feat(chat): add resizable transcript width#266
Merged
su-fen merged 3 commits intoJul 26, 2026
Conversation
- persist the preferred transcript width locally with bilateral resize controls - preserve virtualized row measurements and bottom-follow behavior across width changes - mirror the interaction in desktop and gateway clients
Follow-up to the resizable-transcript-width feature, addressing the review findings without changing the shipped behaviour. - Extract the column geometry into lib/transcript-width/transcriptWidthModel, a dependency-free mirrored leaf. lib/settings now re-exports the bounds from there instead of redeclaring them, so the persisted range and the arithmetic that enforces it cannot drift. - Clamp the width from a layout effect rather than a passive one. The host element's inline style carries the preferred width and this component narrows it to the stage; a passive write landed after paint, flashing the unclamped width for a frame whenever a commit had to be clamped. Both call sites now document that ownership split. - Stop re-arming the stage ResizeObserver on every width commit: it reads the current width through a ref, so the observer is keyed off the host alone. - Step keyboard resizes from the rendered width instead of the stored preference. With a preference wider than the stage, arrow keys walked a value nothing could see and took ~29 presses to move the column. - Expose one focusable separator to assistive tech. aria-value* is only meaningful on a focusable separator, so the left handle is now a pointer-only affordance instead of advertising values nothing can focus to change; both handles carry the same title. - Gate the mount on the same media query the CSS uses, via a shared constant, so a coarse pointer neither renders the handles nor pays for their listeners. - Fall back to the upper bound when the stage is unmeasured, instead of guessing from window.innerWidth, which also counts the sidebar and dock. - Route both transcripts through buildTranscriptLayoutKey, which restores the zero-width guard the plain-number measurement key used to carry. - Anchor the scroll-follow opt-out attribute in scrollFollowCore and build the selector from it, so the widget and the follow engine share one name. - Replace the source-regex tests with behaviour tests over the extracted model: clamping, stage fallback, drag arithmetic, keyboard stepping and layout-key identity. The remaining cross-file assertion derives its expected string from the exported constant rather than hardcoding a pattern. gui tests 1261/1261, gateway webui tests 423/423, both typecheck and build clean, mirror check 106 files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation