Repository navigation
fix(VTextarea): keep native undo history with auto-grow - #23279
Merged
J-Sek merged 4 commits intoOct 19, 2026
Merged
Conversation
auto-grow measured the content with a hidden sizer textarea that gets the value on every input. In Chromium, replacing the content of another element while typing ends the current typing step, so Ctrl+Z undid one character at a time. Where `field-sizing: content` is supported, the textarea now sizes itself: the rows and max rows limits are set as min/max height, and rows and the field height follow its size. Other browsers keep using the sizer. fixes #23153 Co-authored-by: Claude Opus 5.5 <[email protected]>
J-Sek
marked this pull request as ready for review
October 19, 2026 11:38
Contributor
|
Sorry for rushing it out of Draft, it looked really well overall 👍🏼 |
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.
Description
fixes #23153
fixes #21982 + undo/removing hides scrollbar if content actually fits within
max-rowsThis is the
field-sizing: contentapproach @J-Sek suggested, with the JS sizer kept as the fallback.Why undo breaks. auto-grow measures the content with a hidden sizer
<textarea>that gets the value on every input. In Chromium, setting another textarea's value while the user is typing ends the current typing step, so every keystroke became its own undo step. Testing a plain page in Chromium, the same happens when nodes are replaced anywhere in the page, but not when a text node, an attribute or a style changes in place:inputeventhello world foo""sizer.value = value(sync, microtask,requestAnimationFrameorsetTimeout)"hello world fo"div.textContent = value"hello world fo"textNode.data = value, attribute or style changes""So deferring the sizer update doesn't help, and a
<div>mirror would only work if it kept updating one text node in place.What changes. After mount, if
CSS.supports('field-sizing', 'content'):field-sizing: contentandheight: auto(v-textarea--field-sizing).rowsandmax-rows/max-heightare computed as before and applied as--v-textarea-min-height/--v-textarea-max-height.ResizeObserveron the textarea updatesrows(forupdate:rowsandcenter-affix) and the control height from its size.Browsers without
field-sizingkeep using the sizer as before. The check runs after mount, so SSR and hydration render the sizer as today.Same sizes as before. In Chromium I rendered 18 combinations with both paths (the real one and the sizer forced via a mocked
SUPPORTS_FIELD_SIZING) and compared the textarea height, field height, emittedrowsand whether it scrolls. All were identical. The combinations were:rows1 and 3, a trailing newlinemax-rows2 and 4,max-heightOne difference to expect: with
field-sizing: content, an empty textarea is sized to its placeholder, so a placeholder longer than the field could make an empty field taller than before.Tests.
VTextarea.sizer.spec.browser.tsxruns the sizer fallback withSUPPORTS_FIELD_SIZINGmocked tofalse.Markup:
I used Claude Code for this change and reviewed it.