Skip to content

Fix independent panel input resizing#998

Merged
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:fix-firefox-panel-resize
Jul 13, 2026
Merged

Fix independent panel input resizing#998
PeterDaveHello merged 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:fix-firefox-panel-resize

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

  • replace the transformed native resize handle with a pointer-driven separator on the desktop independent conversation page
  • keep the conversation pane usable by clamping the input height and recalculating bounds when the window changes
  • support keyboard resizing with an accessible, localized separator label
  • preserve the existing auto-grow and native resize behavior outside the desktop independent page

Root cause

The independent page requested a reversed native resize direction so users could drag the input area's top edge. The implementation achieved that by rotating a resizable wrapper and its textarea by 180 degrees, but explicitly disabled the workaround in Firefox because it did not behave correctly there. Firefox consequently fell back to a bottom-edge native handle inside a full-height, overflow-hidden panel, making the boundary impractical to resize.

This change removes the browser-specific transform workaround from the desktop independent page and uses Pointer Events with pointer capture instead.

User impact

Firefox users can resize the boundary between the conversation and input areas by dragging the visible separator. Chromium and desktop Safari use the same interaction, while mobile and non-independent conversation cards keep their existing behavior.

Related: #266

Summary by CodeRabbit

  • New Features
    • Added improved resize controls for the input box, including pointer dragging and ArrowUp/ArrowDown plus Home/End shortcuts.
    • Added the localized “Resize input box” label across supported languages.
  • Bug Fixes
    • Improved input resize sizing bounds and responsiveness across layout and window size changes.
    • Fixed sizing behavior in conversation cards when resize clamping is disabled.
  • Tests
    • Added unit tests covering pointer resizing, keyboard resizing, and min/max limits.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a70bc6b-3c3f-4afa-ae9e-173dbb2b788b

📥 Commits

Reviewing files that changed from the base of the PR and between c128aea and 0d5c5f8.

📒 Files selected for processing (18)
  • src/_locales/de/main.json
  • src/_locales/en/main.json
  • src/_locales/es/main.json
  • src/_locales/fr/main.json
  • src/_locales/in/main.json
  • src/_locales/it/main.json
  • src/_locales/ja/main.json
  • src/_locales/ko/main.json
  • src/_locales/pt/main.json
  • src/_locales/ru/main.json
  • src/_locales/tr/main.json
  • src/_locales/zh-hans/main.json
  • src/_locales/zh-hant/main.json
  • src/components/ConversationCard/index.jsx
  • src/components/InputBox/index.jsx
  • src/components/InputBox/resize.mjs
  • src/content-script/styles.scss
  • tests/unit/components/input-box-resize.test.mjs
🚧 Files skipped from review as they are similar to previous changes (16)
  • src/_locales/pt/main.json
  • src/components/ConversationCard/index.jsx
  • src/_locales/tr/main.json
  • src/_locales/it/main.json
  • src/_locales/ru/main.json
  • src/_locales/fr/main.json
  • src/_locales/in/main.json
  • src/_locales/ja/main.json
  • tests/unit/components/input-box-resize.test.mjs
  • src/_locales/de/main.json
  • src/components/InputBox/resize.mjs
  • src/content-script/styles.scss
  • src/_locales/es/main.json
  • src/_locales/en/main.json
  • src/_locales/zh-hant/main.json
  • src/_locales/zh-hans/main.json

📝 Walkthrough

Walkthrough

Adds a top resize handle to InputBox with pointer and keyboard controls, shared height helpers and tests, supporting layout and styling changes, and localized “Resize input box” labels across 13 locales.

Changes

Input Resize

Layer / File(s) Summary
Resize calculation helpers
src/components/InputBox/resize.mjs, tests/unit/components/input-box-resize.test.mjs
Adds clamping, pointer-resize, and keyboard-resize helpers with tests for bounds, steps, shortcuts, and unsupported keys.
InputBox resize control flow
src/components/InputBox/index.jsx
Reworks resize state and bounds calculation, adds pointer and keyboard handlers, and conditionally wires the resize handle and textarea presentation.
Resize layout and visual presentation
src/content-script/styles.scss, src/components/ConversationCard/index.jsx
Adds resize-handle and flex-layout styles and allows the markdown container to shrink within the layout.
Resize control localization
src/_locales/*/main.json
Adds the “Resize input box” label in 13 locale files.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ResizeHandle
  participant InputBox
  participant ResizeHelpers
  participant Textarea
  ResizeHandle->>InputBox: pointer or keyboard resize event
  InputBox->>ResizeHelpers: calculate and clamp height
  ResizeHelpers-->>InputBox: bounded input height
  InputBox->>Textarea: apply height and resize styles
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: fixing input resizing behavior in the independent panel.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a resizable input box feature, adding pointer and keyboard-driven resizing capabilities along with corresponding localization strings, styling, and unit tests. Feedback on the changes suggests cleaning up the unused reverseDivRef reference in InputBox and adding a hover state to the resize handle in the stylesheet to improve discoverability.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/InputBox/index.jsx Outdated
Comment thread src/components/InputBox/index.jsx Outdated
Comment thread src/content-script/styles.scss
@qodo-code-review

qodo-code-review Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used

Grey Divider


Remediation recommended

1. Async focus can throw ✗ Dismissed 🐞 Bug ☼ Reliability ⭐ New
Description
InputBox asynchronously loads config and then calls inputRef.current.focus() inside the promise
callback; if the component unmounts before the storage read resolves, inputRef.current can be null
and .focus() will throw. This can happen when the conversation UI is closed/unmounted while the
async config read is still pending.
Code

src/components/InputBox/index.jsx[R87-89]

  useEffect(() => {
    if (enabled)
      getUserConfig().then((config) => {
Evidence
The InputBox effect schedules an async config read and then focuses the textarea in the .then(...)
callback. Since getUserConfig() awaits Browser.storage.local.get(...), it may resolve later;
meanwhile ConversationCard can be closed (unmounted), which clears refs—making inputRef.current
null at callback time.

src/components/InputBox/index.jsx[87-92]
src/config/index.mjs[1544-1551]
src/components/ConversationCard/index.jsx[376-383]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getUserConfig().then(...)` later calls `inputRef.current.focus()` without checking that the component is still mounted / ref is still non-null.

## Issue Context
`getUserConfig()` performs async `Browser.storage.local.get(...)`, so it can resolve after the component unmounts (e.g., user closes the ConversationCard).

## Fix Focus Areas
- src/components/InputBox/index.jsx[87-92]

## Suggested fix
- Change `inputRef.current.focus()` to `inputRef.current?.focus()` at minimum.
- Preferably, add a mounted/cancelled flag in the effect cleanup and skip focusing if unmounted.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Resize drag steals focus ✓ Resolved 🐞 Bug ≡ Correctness
Description
InputBox.handleResizePointerDown focuses the separator and stopResizing never restores focus to the
textarea, so after a pointer resize the user’s typing/Enter-to-send won’t work until they manually
refocus the input.
Code

src/components/InputBox/index.jsx[R108-141]

+  const handleResizePointerDown = (e) => {
+    if (!e.isPrimary || e.button !== 0) return
+
+    e.currentTarget.focus()
+    e.preventDefault()
+    const maxHeight = getMaxInputHeight()
+    setMaxInputHeight(maxHeight)
+    resizeStartRef.current = {
+      pointerId: e.pointerId,
+      height: inputRef.current.offsetHeight,
+      y: e.clientY,
+      maxHeight,
+    }
+    e.currentTarget.setPointerCapture(e.pointerId)
+  }
+
+  const handleResizePointerMove = (e) => {
+    const resizeStart = resizeStartRef.current
+    if (!resizeStart || resizeStart.pointerId !== e.pointerId) return
+
+    e.preventDefault()
+    setInputHeight(
+      getPointerInputHeight(resizeStart.height, resizeStart.y, e.clientY, resizeStart.maxHeight),
+    )
+  }
+
+  const stopResizing = (e) => {
+    if (resizeStartRef.current?.pointerId !== e.pointerId) return
+
+    resizeStartRef.current = null
+    if (e.currentTarget.hasPointerCapture(e.pointerId)) {
+      e.currentTarget.releasePointerCapture(e.pointerId)
+    }
+  }
Evidence
The resize handle explicitly focuses itself on pointer down, and the resize-stop handler clears
pointer state without restoring focus; the textarea’s key handling (Enter-to-send) only fires when
it has focus.

src/components/InputBox/index.jsx[108-141]
src/components/InputBox/index.jsx[94-106]
src/components/InputBox/index.jsx[176-195]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
While resizing via pointer, `handleResizePointerDown` focuses the separator. After the resize completes (`pointerup`/`pointercancel`/`lostpointercapture`), focus is not returned to the textarea, leaving keyboard input and Enter-to-send inactive until the user clicks the textarea.

### Issue Context
This only affects the new pointer-driven resize handle path (`hasTopResizeHandle`). The textarea’s send behavior is bound to its `onKeyDown`, so losing focus breaks the expected workflow of “resize then keep typing”.

### Fix Focus Areas
- src/components/InputBox/index.jsx[108-141]

### Suggested fix
In `stopResizing`, after releasing pointer capture, restore focus to the textarea (e.g., `inputRef.current?.focus()`) **but only if** the separator is currently focused (to avoid stealing focus if the user clicked elsewhere during/after the drag). Alternatively, remove `e.currentTarget.focus()` from `handleResizePointerDown` and only focus the separator for keyboard-initiated interactions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Keyboard resize may skip steps ✓ Resolved 🐞 Bug ≡ Correctness
Description
InputBox.handleResizeKeyDown computes the next height from the render-captured inputHeight and then
calls setInputHeight(nextHeight), so rapid key repeat/batched updates can apply multiple key events
against the same stale height and drop increments. This makes the newly-added accessible keyboard
resizing less reliable than intended.
Code

src/components/InputBox/index.jsx[R144-152]

+  const handleResizeKeyDown = (e) => {
+    const maxHeight = getMaxInputHeight()
+    const nextHeight = getKeyboardInputHeight(inputHeight, e.key, maxHeight, e.shiftKey)
+    if (nextHeight === null) return
+
+    e.preventDefault()
+    setMaxInputHeight(maxHeight)
+    setInputHeight(nextHeight)
+  }
Evidence
The handler uses getKeyboardInputHeight(inputHeight, ...) where inputHeight is from the current
render closure, then sets state with setInputHeight(nextHeight). Since getKeyboardInputHeight is
incremental (adds/subtracts step), using a non-functional update makes it timing-sensitive under
repeated keydown events.

src/components/InputBox/index.jsx[144-152]
src/components/InputBox/resize.mjs[17-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`handleResizeKeyDown` derives `nextHeight` from the render-captured `inputHeight` and then calls `setInputHeight(nextHeight)`. With rapid key repeat or React batching, multiple keydown events can be processed before a re-render, causing multiple updates to be computed from the same stale height and effectively dropping some resize steps.

## Issue Context
This impacts the independent-panel-only keyboard resizing path (`role="separator"`), so it directly affects the accessibility promise of this PR.

## Fix
Update the keyboard handler to use a functional state update so each keydown computes from the latest committed height, e.g.:
- compute `maxHeight` once per event
- use `setInputHeight((prev) => { const next = getKeyboardInputHeight(prev, e.key, maxHeight, e.shiftKey); return next ?? prev })`
- keep `setMaxInputHeight(maxHeight)` when a resize key is handled

## Fix Focus Areas
- src/components/InputBox/index.jsx[144-152]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Unthrottled pointermove rerenders ✗ Dismissed 🐞 Bug ➹ Performance
Description
InputBox.handleResizePointerMove calls setInputHeight on every pointermove while dragging the
separator, which can trigger very frequent React re-renders and layout work during a drag. This can
cause visible jank in the independent panel when resizing (especially with long conversations).
Code

src/components/InputBox/index.jsx[R125-133]

+  const handleResizePointerMove = (e) => {
+    const resizeStart = resizeStartRef.current
+    if (!resizeStart || resizeStart.pointerId !== e.pointerId) return
+
+    e.preventDefault()
+    setInputHeight(
+      getPointerInputHeight(resizeStart.height, resizeStart.y, e.clientY, resizeStart.maxHeight),
+    )
+  }
Evidence
The resize handle binds onPointerMove to handleResizePointerMove, and that handler calls
setInputHeight(...) on each move event while a resize is active. That produces a React state
update frequency tied directly to pointermove firing rate.

src/components/InputBox/index.jsx[125-133]
src/components/InputBox/index.jsx[156-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
During resizing, every `pointermove` event calls `setInputHeight(...)`. Pointer move events can fire at a high rate, and each `setState` can cause React to re-render and recalculate layout, leading to drag jank.

## Issue Context
This is on a core interaction path for Firefox/Chromium/Safari on the independent conversation page.

## Fix
Throttle height updates to at most once per animation frame:
- store the latest computed height in a ref
- schedule a single `requestAnimationFrame` callback that reads the ref and calls `setInputHeight`
- cancel any pending rAF on resize stop/unmount

(Alternative: update the element style directly during drag and only commit to React state on pointerup, but rAF-throttled state updates are usually sufficient.)

## Fix Focus Areas
- src/components/InputBox/index.jsx[125-133]
- src/components/InputBox/index.jsx[156-174]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Resize constants drift risk ✓ Resolved 🐞 Bug ⚙ Maintainability ⭐ New
Description
InputBox introduces shared resize constants but still hard-codes '70px'/'160px' in styles, which
can silently diverge from MIN_INPUT_HEIGHT/DEFAULT_INPUT_HEIGHT later. This can create
mismatches between actual CSS constraints and the values used for clamping/ARIA attributes.
Code

src/components/InputBox/index.jsx[R188-189]

+          style={{ resize: hasTopResizeHandle ? 'none' : 'vertical', minHeight: '70px' }}
          placeholder={
Evidence
The PR adds constants for resize bounds, but the textarea minHeight and the native maxHeight cap
still use string literals, creating duplicated sources of truth.

src/components/InputBox/resize.mjs[1-3]
src/components/InputBox/index.jsx[48-53]
src/components/InputBox/index.jsx[166-169]
src/components/InputBox/index.jsx[188-189]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`MIN_INPUT_HEIGHT` / `DEFAULT_INPUT_HEIGHT` are defined in `resize.mjs`, but `InputBox` still uses hard-coded `'70px'` and `'160px'` in inline styles.

## Issue Context
This is currently consistent (70/160 match), but future changes can update constants and forget these literals.

## Fix Focus Areas
- src/components/InputBox/resize.mjs[1-3]
- src/components/InputBox/index.jsx[48-53]
- src/components/InputBox/index.jsx[166-169]
- src/components/InputBox/index.jsx[188-189]

## Suggested fix
- Use `${DEFAULT_INPUT_HEIGHT}px` instead of `'160px'`.
- Use `${MIN_INPUT_HEIGHT}px` instead of `'70px'` (or move min-height to CSS driven by a variable).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit 0d5c5f8

Results up to commit cbcb30e


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Keyboard resize may skip steps ✓ Resolved 🐞 Bug ≡ Correctness
Description
InputBox.handleResizeKeyDown computes the next height from the render-captured inputHeight and then
calls setInputHeight(nextHeight), so rapid key repeat/batched updates can apply multiple key events
against the same stale height and drop increments. This makes the newly-added accessible keyboard
resizing less reliable than intended.
Code

src/components/InputBox/index.jsx[R144-152]

+  const handleResizeKeyDown = (e) => {
+    const maxHeight = getMaxInputHeight()
+    const nextHeight = getKeyboardInputHeight(inputHeight, e.key, maxHeight, e.shiftKey)
+    if (nextHeight === null) return
+
+    e.preventDefault()
+    setMaxInputHeight(maxHeight)
+    setInputHeight(nextHeight)
+  }
Evidence
The handler uses getKeyboardInputHeight(inputHeight, ...) where inputHeight is from the current
render closure, then sets state with setInputHeight(nextHeight). Since getKeyboardInputHeight is
incremental (adds/subtracts step), using a non-functional update makes it timing-sensitive under
repeated keydown events.

src/components/InputBox/index.jsx[144-152]
src/components/InputBox/resize.mjs[17-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`handleResizeKeyDown` derives `nextHeight` from the render-captured `inputHeight` and then calls `setInputHeight(nextHeight)`. With rapid key repeat or React batching, multiple keydown events can be processed before a re-render, causing multiple updates to be computed from the same stale height and effectively dropping some resize steps.

## Issue Context
This impacts the independent-panel-only keyboard resizing path (`role="separator"`), so it directly affects the accessibility promise of this PR.

## Fix
Update the keyboard handler to use a functional state update so each keydown computes from the latest committed height, e.g.:
- compute `maxHeight` once per event
- use `setInputHeight((prev) => { const next = getKeyboardInputHeight(prev, e.key, maxHeight, e.shiftKey); return next ?? prev })`
- keep `setMaxInputHeight(maxHeight)` when a resize key is handled

## Fix Focus Areas
- src/components/InputBox/index.jsx[144-152]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unthrottled pointermove rerenders ✗ Dismissed 🐞 Bug ➹ Performance
Description
InputBox.handleResizePointerMove calls setInputHeight on every pointermove while dragging the
separator, which can trigger very frequent React re-renders and layout work during a drag. This can
cause visible jank in the independent panel when resizing (especially with long conversations).
Code

src/components/InputBox/index.jsx[R125-133]

+  const handleResizePointerMove = (e) => {
+    const resizeStart = resizeStartRef.current
+    if (!resizeStart || resizeStart.pointerId !== e.pointerId) return
+
+    e.preventDefault()
+    setInputHeight(
+      getPointerInputHeight(resizeStart.height, resizeStart.y, e.clientY, resizeStart.maxHeight),
+    )
+  }
Evidence
The resize handle binds onPointerMove to handleResizePointerMove, and that handler calls
setInputHeight(...) on each move event while a resize is active. That produces a React state
update frequency tied directly to pointermove firing rate.

src/components/InputBox/index.jsx[125-133]
src/components/InputBox/index.jsx[156-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
During resizing, every `pointermove` event calls `setInputHeight(...)`. Pointer move events can fire at a high rate, and each `setState` can cause React to re-render and recalculate layout, leading to drag jank.

## Issue Context
This is on a core interaction path for Firefox/Chromium/Safari on the independent conversation page.

## Fix
Throttle height updates to at most once per animation frame:
- store the latest computed height in a ref
- schedule a single `requestAnimationFrame` callback that reads the ref and calls `setInputHeight`
- cancel any pending rAF on resize stop/unmount

(Alternative: update the element style directly during drag and only commit to React state on pointerup, but rAF-throttled state updates are usually sufficient.)

## Fix Focus Areas
- src/components/InputBox/index.jsx[125-133]
- src/components/InputBox/index.jsx[156-174]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit d936702


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Resize drag steals focus ✓ Resolved 🐞 Bug ≡ Correctness
Description
InputBox.handleResizePointerDown focuses the separator and stopResizing never restores focus to the
textarea, so after a pointer resize the user’s typing/Enter-to-send won’t work until they manually
refocus the input.
Code

src/components/InputBox/index.jsx[R108-141]

+  const handleResizePointerDown = (e) => {
+    if (!e.isPrimary || e.button !== 0) return
+
+    e.currentTarget.focus()
+    e.preventDefault()
+    const maxHeight = getMaxInputHeight()
+    setMaxInputHeight(maxHeight)
+    resizeStartRef.current = {
+      pointerId: e.pointerId,
+      height: inputRef.current.offsetHeight,
+      y: e.clientY,
+      maxHeight,
+    }
+    e.currentTarget.setPointerCapture(e.pointerId)
+  }
+
+  const handleResizePointerMove = (e) => {
+    const resizeStart = resizeStartRef.current
+    if (!resizeStart || resizeStart.pointerId !== e.pointerId) return
+
+    e.preventDefault()
+    setInputHeight(
+      getPointerInputHeight(resizeStart.height, resizeStart.y, e.clientY, resizeStart.maxHeight),
+    )
+  }
+
+  const stopResizing = (e) => {
+    if (resizeStartRef.current?.pointerId !== e.pointerId) return
+
+    resizeStartRef.current = null
+    if (e.currentTarget.hasPointerCapture(e.pointerId)) {
+      e.currentTarget.releasePointerCapture(e.pointerId)
+    }
+  }
Evidence
The resize handle explicitly focuses itself on pointer down, and the resize-stop handler clears
pointer state without restoring focus; the textarea’s key handling (Enter-to-send) only fires when
it has focus.

src/components/InputBox/index.jsx[108-141]
src/components/InputBox/index.jsx[94-106]
src/components/InputBox/index.jsx[176-195]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
While resizing via pointer, `handleResizePointerDown` focuses the separator. After the resize completes (`pointerup`/`pointercancel`/`lostpointercapture`), focus is not returned to the textarea, leaving keyboard input and Enter-to-send inactive until the user clicks the textarea.

### Issue Context
This only affects the new pointer-driven resize handle path (`hasTopResizeHandle`). The textarea’s send behavior is bound to its `onKeyDown`, so losing focus breaks the expected workflow of “resize then keep typing”.

### Fix Focus Areas
- src/components/InputBox/index.jsx[108-141]

### Suggested fix
In `stopResizing`, after releasing pointer capture, restore focus to the textarea (e.g., `inputRef.current?.focus()`) **but only if** the separator is currently focused (to avoid stealing focus if the user clicked elsewhere during/after the drag). Alternatively, remove `e.currentTarget.focus()` from `handleResizePointerDown` and only focus the separator for keyboard-initiated interactions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a top resize handle for the input box on non-mobile platforms, allowing users to resize the input box using pointer and keyboard controls. It adds corresponding localization strings, a helper module for height calculations with unit tests, and minor layout adjustments to the conversation card. The review feedback suggests using useLayoutEffect instead of useEffect to prevent layout flickers during resizing, removing the unused reverseDivRef reference, and replacing the undefined --font-active-color CSS variable with var(--color-accent-fg) for consistent focus styles.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/content-script/styles.scss
Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx Outdated
@PeterDaveHello
PeterDaveHello force-pushed the fix-firefox-panel-resize branch from cbcb30e to d936702 Compare July 10, 2026 22:05

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces custom top-resizing functionality for the InputBox component, replacing the previous native vertical resizing logic when reverseResizeDir is active. It includes localization updates, style changes, a new helper module for calculating input height, and corresponding unit tests. The review feedback highlights opportunities to improve performance by adding a missing dependency array to a useEffect hook to prevent unnecessary layout reflows during typing, and by using the inputHeight state instead of reading offsetHeight from the DOM.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit d936702

@PeterDaveHello
PeterDaveHello force-pushed the fix-firefox-panel-resize branch from d936702 to c128aea Compare July 10, 2026 22:20

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the CSS-based vertical resizing of the input box with a custom, accessible resizing mechanism using pointer and keyboard events. It introduces a new helper module (resize.mjs) with corresponding unit tests, updates localizations across multiple languages, and styles the new resize handle. The review feedback highlights that the CSS variable --font-active-color used for the hover and focus states of the resize handle is undefined, which could lead to accessibility issues, and suggests using an existing variable like --font-color instead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/content-script/styles.scss
Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit c128aea

@PeterDaveHello
PeterDaveHello requested a review from Copilot July 11, 2026 04:01
@PeterDaveHello
PeterDaveHello marked this pull request as ready for review July 11, 2026 04:01
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Fix independent conversation input resizing with pointer/keyboard separator

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Replace flipped native resize handle with a pointer-captured, accessible separator on desktop
 independent page.
• Clamp and recompute input-height bounds to keep conversation pane usable on window resize.
• Add localized separator label plus unit tests for pointer and keyboard resize math.
Diagram

graph TD
  A["Independent conversation UI"] --> B["Conversation pane"] --> C["Resize separator"] --> D["InputBox"]
  C --> E[["resize.mjs helpers"]]
  E --> D
  D --> F["styles.scss"]
  G["_locales/*/main.json"] --> D
  H["input-box-resize.test.mjs"] --> E

  subgraph Legend
    direction LR
    _ui["UI / Component"] ~~~ _util[["Helper module"]] ~~~ _data["Resource / Asset"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep native textarea resize + CSS transform workaround
  • ➕ Less custom event handling; relies on browser-native resize UI
  • ➖ Transform-based inversion is brittle across browsers (already broken in Firefox)
  • ➖ Harder to make accessible/keyboard-operable consistently
  • ➖ Complex layout interactions with overflow/height constraints
2. Use a dedicated split-pane/sash library for vertical resizing
  • ➕ Battle-tested pointer capture, keyboard support, and accessibility patterns
  • ➖ Adds dependency weight and integration surface area for a small feature
  • ➖ May be harder to scope to only the independent conversation page

Recommendation: The PR’s pointer-captured separator is the best fit: it removes browser-specific transform hacks, works consistently in Firefox/Chromium/Safari, and enables explicit ARIA + keyboard resizing while keeping native textarea resize elsewhere.

Files changed (18) +254 / -37

Enhancement (1) +34 / -0
styles.scssStyle the new resize separator and fixed-height input container +34/-0

Style the new resize separator and fixed-height input container

• Adds visual affordance, cursor/touch behavior, and focus-visible outline for the separator, plus layout rules for the fixed-height input wrapper.

src/content-script/styles.scss

Bug fix (2) +133 / -37
index.jsxPrevent conversation pane flex overflow when not clamped +1/-1

Prevent conversation pane flex overflow when not clamped

• Adds minHeight: 0 to the growable conversation container so the layout can shrink correctly when the input height increases.

src/components/ConversationCard/index.jsx

index.jsxImplement pointer/keyboard-driven top-edge resizing for independent input +132/-36

Implement pointer/keyboard-driven top-edge resizing for independent input

• Replaces the rotated native resize workaround with an explicit separator that uses pointer capture and keyboard controls to adjust input height. Computes and clamps max input height based on container/conversation bounds and updates on window resize while preserving native textarea resizing outside this mode.

src/components/InputBox/index.jsx

Refactor (1) +32 / -0
resize.mjsAdd shared clamp and height calculation helpers for resizing +32/-0

Add shared clamp and height calculation helpers for resizing

• Introduces constants and pure functions for clamping input height and computing pointer/keyboard-driven resizing steps.

src/components/InputBox/resize.mjs

Tests (1) +42 / -0
input-box-resize.test.mjsAdd unit tests for pointer and keyboard resize calculations +42/-0

Add unit tests for pointer and keyboard resize calculations

• Covers clamp behavior, pointer-driven height deltas, keyboard step sizing (including shift), and min/max bounds enforcement.

tests/unit/components/input-box-resize.test.mjs

Other (13) +13 / -0
main.jsonAdd German label for input resize separator +1/-0

Add German label for input resize separator

• Introduces the "Resize input box" translation used for the separator aria-label.

src/_locales/de/main.json

main.jsonAdd English label for input resize separator +1/-0

Add English label for input resize separator

• Adds the "Resize input box" string consumed by the new accessible separator.

src/_locales/en/main.json

main.jsonAdd Spanish label for input resize separator +1/-0

Add Spanish label for input resize separator

• Introduces the Spanish translation for the separator aria-label.

src/_locales/es/main.json

main.jsonAdd French label for input resize separator +1/-0

Add French label for input resize separator

• Introduces the French translation for the separator aria-label.

src/_locales/fr/main.json

main.jsonAdd Indonesian label for input resize separator +1/-0

Add Indonesian label for input resize separator

• Introduces the Indonesian translation for the separator aria-label.

src/_locales/in/main.json

main.jsonAdd Italian label for input resize separator +1/-0

Add Italian label for input resize separator

• Introduces the Italian translation for the separator aria-label.

src/_locales/it/main.json

main.jsonAdd Japanese label for input resize separator +1/-0

Add Japanese label for input resize separator

• Introduces the Japanese translation for the separator aria-label.

src/_locales/ja/main.json

main.jsonAdd Korean label for input resize separator +1/-0

Add Korean label for input resize separator

• Introduces the Korean translation for the separator aria-label.

src/_locales/ko/main.json

main.jsonAdd Portuguese label for input resize separator +1/-0

Add Portuguese label for input resize separator

• Introduces the Portuguese translation for the separator aria-label.

src/_locales/pt/main.json

main.jsonAdd Russian label for input resize separator +1/-0

Add Russian label for input resize separator

• Introduces the Russian translation for the separator aria-label.

src/_locales/ru/main.json

main.jsonAdd Turkish label for input resize separator +1/-0

Add Turkish label for input resize separator

• Introduces the Turkish translation for the separator aria-label.

src/_locales/tr/main.json

main.jsonAdd Simplified Chinese label for input resize separator +1/-0

Add Simplified Chinese label for input resize separator

• Introduces the Simplified Chinese translation for the separator aria-label.

src/_locales/zh-hans/main.json

main.jsonAdd Traditional Chinese label for input resize separator +1/-0

Add Traditional Chinese label for input resize separator

• Introduces the Traditional Chinese translation for the separator aria-label.

src/_locales/zh-hant/main.json

@kilo-code-bot

kilo-code-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No New Issues Found | Recommendation: Address existing review comments before merge

The changed code (pointer/keyboard-driven input resize handle, resize.mjs helpers, styles, and locale additions) was reviewed against the current HEAD (c128aea). Every genuine issue in the changed lines is already covered by active inline comments from existing reviewers (gemini-code-assist, qodo). To avoid duplicates, no new inline comments were posted.

Already-covered issues (no duplicates posted)
  • src/components/InputBox/index.jsx L54 — useEffect missing dependency array (reflows on every keystroke)
  • src/components/InputBox/index.jsx L89 — async getUserConfig().then calls inputRef.current.focus() without null guard
  • src/components/InputBox/index.jsx L120 — reads offsetHeight instead of inputHeight state
  • src/components/InputBox/index.jsx L132 — unthrottled pointermove state updates
  • src/components/InputBox/index.jsx L181 — unused reverseDivRef
  • src/components/InputBox/index.jsx L189 — hard-coded 70px/160px can drift from resize constants
  • src/content-script/styles.scss L1359 — resize handle lacks hover feedback
  • src/content-script/styles.scss L1380 — --font-active-color appears undefined (focus/hover invisible)
  • L143 (focus restore) and L154 (functional keyboard update) — already resolved in current code
Files Reviewed (18 files)
  • src/components/InputBox/index.jsx
  • src/components/InputBox/resize.mjs
  • src/components/ConversationCard/index.jsx
  • src/content-script/styles.scss
  • src/_locales/*/main.json (13 locale files — added Resize input box string)
  • tests/unit/components/input-box-resize.test.mjs
Previous Review Summary (commit c128aea)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit c128aea)

Status: No New Issues Found | Recommendation: Address existing review comments before merge

The changed code (pointer/keyboard-driven input resize handle, resize.mjs helpers, styles, and locale additions) was reviewed against the current HEAD (c128aea). Every genuine issue in the changed lines is already covered by active inline comments from existing reviewers (gemini-code-assist, qodo). To avoid duplicates, no new inline comments were posted.

Already-covered issues (no duplicates posted)
  • src/components/InputBox/index.jsx L54 — useEffect missing dependency array (reflows on every keystroke)
  • src/components/InputBox/index.jsx L89 — async getUserConfig().then calls inputRef.current.focus() without null guard
  • src/components/InputBox/index.jsx L120 — reads offsetHeight instead of inputHeight state
  • src/components/InputBox/index.jsx L132 — unthrottled pointermove state updates
  • src/components/InputBox/index.jsx L181 — unused reverseDivRef
  • src/components/InputBox/index.jsx L189 — hard-coded 70px/160px can drift from resize constants
  • src/content-script/styles.scss L1359 — resize handle lacks hover feedback
  • src/content-script/styles.scss L1380 — --font-active-color appears undefined (focus/hover invisible)
  • L143 (focus restore) and L154 (functional keyboard update) — already resolved in current code
Files Reviewed (18 files)
  • src/components/InputBox/index.jsx
  • src/components/InputBox/resize.mjs
  • src/components/ConversationCard/index.jsx
  • src/content-script/styles.scss
  • src/_locales/*/main.json (13 locale files — added Resize input box string)
  • tests/unit/components/input-box-resize.test.mjs

Reviewed by hy3:free · Input: 66.9K · Output: 7.6K · Cached: 277.5K

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes input resizing on the desktop Independent Panel by replacing the prior transform-based native resize workaround with a dedicated, pointer-driven separator (with pointer capture) and keyboard resizing support, while keeping non-independent/mobile behavior unchanged.

Changes:

  • Add pointer + keyboard resizing logic for the Independent Panel input area, including bounds recalculation on window resize.
  • Introduce shared resize helper utilities with unit tests.
  • Add styling for the new resize handle and minor layout adjustment to keep the conversation pane flexing correctly; localize the new accessible label.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/components/input-box-resize.test.mjs Adds unit coverage for pointer/keyboard resize calculations and clamping behavior.
src/content-script/styles.scss Adds styles for the new separator handle and a wrapper class for the resizable input region.
src/components/InputBox/resize.mjs Introduces shared constants + helper functions for clamping and computing resized heights.
src/components/InputBox/index.jsx Implements the separator-driven resizing (pointer capture + keyboard), window-resize bound recalculation, and ARIA labeling.
src/components/ConversationCard/index.jsx Ensures the conversation pane can shrink in flex layout (minHeight: 0) when unclamped (Independent Panel).
src/_locales/en/main.json Adds localized string for the separator label (“Resize input box”).
src/_locales/de/main.json Adds localized string for the separator label.
src/_locales/es/main.json Adds localized string for the separator label.
src/_locales/fr/main.json Adds localized string for the separator label.
src/_locales/in/main.json Adds localized string for the separator label.
src/_locales/it/main.json Adds localized string for the separator label.
src/_locales/ja/main.json Adds localized string for the separator label.
src/_locales/ko/main.json Adds localized string for the separator label.
src/_locales/pt/main.json Adds localized string for the separator label.
src/_locales/ru/main.json Adds localized string for the separator label.
src/_locales/tr/main.json Adds localized string for the separator label.
src/_locales/zh-hans/main.json Adds localized string for the separator label.
src/_locales/zh-hant/main.json Adds localized string for the separator label.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit c128aea

Replace the browser-specific transformed resize handle with an
accessible pointer-driven separator so Firefox can adjust the input
area from its top edge.

Clamp the input height to keep the conversation pane usable, preserve
native resizing outside the independent panel, and cover the shared
resize calculations with unit tests.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a resizable input box feature, allowing users to adjust the input height using pointer or keyboard controls. It includes localization updates, styling adjustments, and unit tests for the resize helper functions. The review feedback suggests adding defensive checks for inputRef.current to prevent potential null pointer exceptions, utilizing a ResizeObserver instead of a window resize listener for more robust layout handling, and providing a fallback for the --font-active-color CSS variable to ensure proper styling and accessibility.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx
Comment thread src/components/InputBox/index.jsx
Comment thread src/content-script/styles.scss

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 0d5c5f8

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

@PeterDaveHello
PeterDaveHello merged commit d7e0661 into ChatGPTBox-dev:master Jul 13, 2026
4 checks passed
@PeterDaveHello
PeterDaveHello deleted the fix-firefox-panel-resize branch July 13, 2026 18:40
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.

2 participants