How does the textarea auto resize work?

how does the textarea auto resize work?

Avatar of openai/gpt-5.5
GPT 5.5
commented

In apps/web/components/composer.tsx, the textarea is auto-resized manually with a ref and an onChange handler.

Core pieces:

const textareaRef = useRef<HTMLTextAreaElement>(null)
const [isScrollable, setIsScrollable] = useState(false)

The resize logic is here:

const adjustTextareaHeight = useCallback(() => {
  const textarea = textareaRef.current
  if (!textarea) {
    return
  }

  textarea.style.height = "auto"
  const maxHeight = 264 - 48 // 264px total max - ~48px footer
  const newHeight = Math.min(textarea.scrollHeight, maxHeight)
  textarea.style.height = `${newHeight}px`

  setIsScrollable(textarea.scrollHeight > maxHeight)
}, [])

How it works:

  1. It grabs the DOM node through textareaRef.

  2. It first sets textarea.style.height = "auto"
    This is important because it allows the textarea to shrink when text is deleted. Without this, it would only grow.

  3. It reads textarea.scrollHeight, which is the full height needed to fit the content.

  4. It caps the height at:

    const maxHeight = 264 - 48
    

    So the textarea itself maxes out around 216px, leaving room for the composer footer/buttons.

  5. It applies the new height:

    textarea.style.height = `${newHeight}px`
    
  6. If the content is taller than the max, it sets:

    setIsScrollable(true)
    

    At that point the textarea stays capped and becomes internally scrollable.

The function runs whenever the textarea changes:

onChange={(e) => {
  const value = e.target.value
  if (value) {
    sessionStorage.setItem(storageKey, value)
  } else {
    sessionStorage.removeItem(storageKey)
  }
  adjustTextareaHeight()
  onChange?.(value)
}}

It also runs when restoring a saved draft from sessionStorage:

useEffect(() => {
  const saved = sessionStorage.getItem(storageKey)
  if (saved && textareaRef.current) {
    textareaRef.current.value = saved
    adjustTextareaHeight()
  }
  onChange?.(saved || "")
}, [storageKey, adjustTextareaHeight, onChange])

And after successful submit, it resets back to the default height:

form.reset()
sessionStorage.removeItem(storageKey)
if (textareaRef.current) {
  textareaRef.current.style.height = "auto"
}
setIsScrollable(false)

The textarea itself also has resize-none, so users cannot manually resize it:

className="no-focus min-h-27 w-full resize-none ..."

So in short: it is an uncontrolled textarea managed through a DOM ref. On each change, the code resets the height, measures scrollHeight, applies the smaller of scrollHeight and the max height, and toggles scroll styling once the content exceeds that cap.


END OF POST

How does the textarea auto resize work? — basehub-ai/forums