Skip to content

fix(web): re-measure a textarea whose height was computed before layout - #1680

Open
takke1986 wants to merge 1 commit into
aws-samples:mainfrom
takke1986:fix/textarea-autosize-border
Open

fix(web): re-measure a textarea whose height was computed before layout#1680
takke1986 wants to merge 1 commit into
aws-samples:mainfrom
takke1986:fix/textarea-autosize-border

Conversation

@takke1986

@takke1986 takke1986 commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Updated. My first version of this PR only corrected a 2px border-box miscalculation and I noted that I could not reproduce the reported symptom. I have since found the real cause and rewritten the fix. Details below.

Description of Changes

The auto-size effect in Textarea runs on mount and depends on the value:

useLayoutEffect(() => {
  ...
  const scrollHeight = ref.current.scrollHeight;
  ref.current.style.height = scrollHeight + 'px';
}, [props.value, props.resizable, maxHeight]);

When it runs before the element has been laid out, scrollHeight is 0, so the height is
set to 0px.
That is what happens inside the dialog ModalSystemContext renders. Because
the effect only depends on the value, a textarea whose value never changes afterwards keeps
height: 0px forever, and overflow-y: hidden hides the content.

This is invisible in development. main.tsx wraps the tree in React.StrictMode, which
invokes effects twice, and the second run happens after layout and repairs the height. In a
production build the effect runs once, so the modal stays broken — which is why #1171
reproduces on a deployed environment but not with npm run dev.

Measured

I rendered ModalSystemContext in isolation and measured it in a headless browser, toggling
StrictMode to reproduce a production build:

style.height clientHeight scrollHeight
StrictMode on (dev), before 36px 34 36
StrictMode off (prod), before 0px 12 (padding only) 36
StrictMode on, after 38px 36 36
StrictMode off, after 38px 36 36

The 0px row is the bug, and it matches the screenshot in #1171.

The fix

  • observe the element with a ResizeObserver and re-measure whenever its box changes, so
    the height catches up once the element is laid out. A re-entrancy guard keeps the observer
    from reacting to the height it sets itself
  • also add the border back to the computed height: scrollHeight covers the content and the
    padding but not the border, while the assigned height is interpreted as the full border
    box because Tailwind sets box-sizing: border-box (this is the 2px in the table above)

Scope: Textarea is used in 13 places, but only ones whose value never changes after
mount can get stuck; everywhere else the height is recomputed on each keystroke, which is
why this has not been noticed more widely. ModalSystemContext is used by ChatPage,
RagKnowledgeBasePage and SharedChatPage, so the RAG chat is affected too.

Compatibility: no API change. Textareas that were already sized correctly get 2px taller
(the border); ones that were stuck at 0px now size to their content.

Checklist

  • Modified relevant documentation — n/a (shared component; the reason is captured in
    comments next to the calculation)
  • Verified operation in local environment (headless browser, measurements above)
  • Executed npm run cdk:test — no changes under packages/cdk, snapshots unaffected

Also run:

  • npm run web:test — 278 passed
  • eslint and prettier --check clean

Related Issues

The auto-size effect runs once on mount and depends on the value. When it
runs before the element has been laid out - which is what happens inside
the dialog that ModalSystemContext renders - scrollHeight is 0, so the
height is set to 0px. A textarea whose value never changes afterwards
keeps that height forever and its content is hidden behind
overflow-y: hidden.

This is invisible in development because StrictMode invokes the effect
twice and the second run happens after layout, which is why it only
reproduces in a deployed build.

Observe the element and re-measure whenever its box changes, so the height
catches up once the element is laid out.

Also add the border back to the computed height: scrollHeight covers the
content and the padding but not the border, while the assigned height is
interpreted as the full border box.

Measured in the modal with StrictMode disabled, matching a production build:

  before  height=0px  clientHeight=12 scrollHeight=36
  after   height=38px clientHeight=36 scrollHeight=36
@takke1986
takke1986 force-pushed the fix/textarea-autosize-border branch from 4d4f219 to 21e89c5 Compare August 22, 2026 15:02
@takke1986 takke1986 changed the title fix(web): add the border back when auto-sizing a textarea fix(web): re-measure a textarea whose height was computed before layout Aug 22, 2026
@takke1986

Copy link
Copy Markdown
Contributor Author

befor
1171_prod_before
3lines(ex)
1171_prod_before_3lines
after
1171_prod_after
3lines(ex)
1171_prod_after_3lines

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