Skip to content

Replace the composer's JS autosize with native field-sizing - #384

Merged
dovvnloading merged 1 commit into
mainfrom
fix/composer-autosize-field-sizing
Sep 1, 2026
Merged

dovvnloading merged 1 commit into
mainfrom
fix/composer-autosize-field-sizing

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Problem

The composer textarea sized itself with a one-shot layout effect: reset height to auto, read scrollHeight, clamp to 42-160px, re-running only when the draft text changed. A scrollHeight read is only as good as the layout at the instant it runs, so any mount under a transient layout - a viewport resized after load, a zoom or DPI change - baked a wrong height into the inline style, and nothing corrected it until the next keystroke. In the failure mode this fix was traced from, an empty one-row composer rendered pinned at the 160px ceiling.

Change

field-sizing: content on .composer-input, with min-height: 42px / max-height: 160px / overflow-y: auto. The height now tracks the content continuously instead of being sampled once, so it cannot go stale. Textareas are border-box in Chromium's UA sheet, so the bounds match the old JS 42-160 range exactly; this is the same native-autosize posture the code-sandbox card's inputs already use. The layout effect, the ref that existed only for it, and the now-unused useLayoutEffect/useRef imports are removed; the skip-link jump target is the element id and is unchanged.

Test plan

  • Composer.test.tsx: 38 pass unchanged.
  • npm run check (schema drift, typecheck, lint, vitest, build, bundle size) against a clean checkout of this branch: 2135 pass.
  • Manual against the built bundle at the app's real 1440x900 window: empty composer renders at the same geometry as before the change (textarea 50px, dock 114px, no inline height); a four-line draft grows it to ~81px and clearing returns it to 50px; two live viewport resizes with no reload leave it at 50px, the exact sequence that previously left the old implementation stuck at 160px.

The composer textarea sized itself with a one-shot layout effect: reset
height to auto, read scrollHeight, clamp to 42-160px, re-running only when
the draft text changed. A scrollHeight read is only as good as the layout
at the instant it runs - any mount under a transient layout (an emulated
viewport resized after load, a zoom or DPI change) bakes a wrong height in
until the next keystroke.

field-sizing: content on the textarea tracks the content continuously with
the same 42-160px bounds (textareas are border-box in Chromium's UA sheet,
so min/max-height match the old JS range exactly). The effect, the ref it
existed for, and the useLayoutEffect/useRef imports are removed; the
skip-link target is the element id and is unchanged. Same native-autosize
posture the code-sandbox card's inputs already use.

Co-Authored-By: Claude <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit a6e1c08 into main Sep 1, 2026
4 checks passed
@dovvnloading
dovvnloading deleted the fix/composer-autosize-field-sizing branch September 1, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant