[PR #200] [MERGED] Delegate scollbox insertBefore to content to fix “Anchor does not exist” error #366

Closed
opened 2026-03-02 23:46:10 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/anomalyco/opentui/pull/200
Author: @eli0shin
Created: 10/5/2025
Status: Merged
Merged: 10/5/2025
Merged by: @kommander

Base: mainHead: scrollbox-insert-before-fix


📝 Commits (1)

  • 54473e2 Delegate scollbox insertBefore to content to fix Anchor not found error

📊 Changes

2 files changed (+46 additions, -1 deletions)

View changed files

📝 packages/core/src/renderables/ScrollBox.ts (+4 -0)
📝 packages/core/src/tests/scrollbox.test.ts (+42 -1)

📄 Description

Resolves https://github.com/sst/opentui/issues/199

The Bug

When inserting a React element in the middle of a list inside a <scrollbox>, the application crashes with:

Error: Anchor does not exist
  at insertBefore (packages/core/src/Renderable.ts:1118:17)
  at insertBefore (packages/react/src/reconciler/host-config.ts:65:12)

Root Cause

ScrollBox has an internal wrapper structure where user content is added to a nested child (this.content), not directly to the ScrollBox instance. The component hierarchy looks like:

ScrollBox
├── wrapper (scroll-box-wrapper)
│   └── viewport
│       └── content ← User children go here
└── scrollbar (scroll-box-vertical-scrollbar)

ScrollBox correctly overrides add() and remove() to delegate to this.content:

  • add(obj, index)this.content.add(obj, index)
  • remove(id)this.content.remove(id)

However, ScrollBox was missing an override for insertBefore().

When React inserts an element in the middle of a list (e.g., when a conditional element appears after initial render), it calls:

parent.insertBefore(newChild, anchorChild)

Without the override, this uses the base Renderable.insertBefore() which:

  1. Looks for anchorChild in the parent's direct children via renderableMapById
  2. Fails because anchorChild is actually in this.content (the wrapper), not in ScrollBox's direct children

The Fix

Added insertBefore() override in ScrollBox to delegate to this.content, matching the pattern used for add() and remove():

Impact Analysis

Affected Components

  • ScrollBox - Fixed by adding insertBefore() override
  • TextRenderable - Already had proper insertBefore() delegation

Affected Renderers

  • React - Was affected (uses insertBefore() directly)
  • Solid - Not affected (uses add(node, anchorIndex) pattern)
  • Vue - Not affected (uses add(node, anchorIndex) pattern)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/anomalyco/opentui/pull/200 **Author:** [@eli0shin](https://github.com/eli0shin) **Created:** 10/5/2025 **Status:** ✅ Merged **Merged:** 10/5/2025 **Merged by:** [@kommander](https://github.com/kommander) **Base:** `main` ← **Head:** `scrollbox-insert-before-fix` --- ### 📝 Commits (1) - [`54473e2`](https://github.com/anomalyco/opentui/commit/54473e2431fa0bc726f924a9acf69626751f8583) Delegate scollbox insertBefore to content to fix Anchor not found error ### 📊 Changes **2 files changed** (+46 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `packages/core/src/renderables/ScrollBox.ts` (+4 -0) 📝 `packages/core/src/tests/scrollbox.test.ts` (+42 -1) </details> ### 📄 Description Resolves https://github.com/sst/opentui/issues/199 ## The Bug When inserting a React element in the middle of a list inside a `<scrollbox>`, the application crashes with: ``` Error: Anchor does not exist at insertBefore (packages/core/src/Renderable.ts:1118:17) at insertBefore (packages/react/src/reconciler/host-config.ts:65:12) ``` ## Root Cause ScrollBox has an internal wrapper structure where user content is added to a nested child (`this.content`), not directly to the ScrollBox instance. The component hierarchy looks like: ``` ScrollBox ├── wrapper (scroll-box-wrapper) │ └── viewport │ └── content ← User children go here └── scrollbar (scroll-box-vertical-scrollbar) ``` ScrollBox correctly overrides `add()` and `remove()` to delegate to `this.content`: - `add(obj, index)` → `this.content.add(obj, index)` ✓ - `remove(id)` → `this.content.remove(id)` ✓ **However, ScrollBox was missing an override for `insertBefore()`.** When React inserts an element in the middle of a list (e.g., when a conditional element appears after initial render), it calls: ```typescript parent.insertBefore(newChild, anchorChild) ``` Without the override, this uses the base `Renderable.insertBefore()` which: 1. Looks for `anchorChild` in the parent's direct children via `renderableMapById` 2. Fails because `anchorChild` is actually in `this.content` (the wrapper), not in ScrollBox's direct children ## The Fix Added `insertBefore()` override in ScrollBox to delegate to `this.content`, matching the pattern used for `add()` and `remove()`: ## Impact Analysis ### Affected Components - ✅ **ScrollBox** - Fixed by adding `insertBefore()` override - ✅ **TextRenderable** - Already had proper `insertBefore()` delegation ### Affected Renderers - ❌ **React** - Was affected (uses `insertBefore()` directly) - ✅ **Solid** - Not affected (uses `add(node, anchorIndex)` pattern) - ✅ **Vue** - Not affected (uses `add(node, anchorIndex)` pattern) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-02 23:46:10 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/opentui#366
No description provided.