From 8ed55c43c7173a2f070893787092d920733249cd Mon Sep 17 00:00:00 2001 From: "tao.chen" <93983997+taochen-ct@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:54:07 +0800 Subject: [PATCH] fix: attach inline prompt to cell.inputArea (under the editor), not cell.node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the inline prompt was Widget.attach'd to cell.node, which in JupyterLab places it at the very bottom of the cell (after the output area and In/Out prompt) — so the user couldn't see it, especially on taller cells. Attaching to cell.inputArea.node puts the prompt directly under the editor, which is the natural inline position. Falls back to cell.node if inputArea is unexpectedly null. Co-Authored-By: Claude Fable 5 --- src/__tests__/opencode_cell_actions.spec.ts | 11 ++++++----- src/components/opencode_cell_actions.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/__tests__/opencode_cell_actions.spec.ts b/src/__tests__/opencode_cell_actions.spec.ts index 0ea462d..fa2eada 100644 --- a/src/__tests__/opencode_cell_actions.spec.ts +++ b/src/__tests__/opencode_cell_actions.spec.ts @@ -87,6 +87,7 @@ function makeFakeCell( const cell = new (CodeCell as unknown as new () => CodeCell)(); (cell as any).model = model; (cell as any).node = document.createElement('div'); + (cell as any).inputArea = { node: document.createElement('div') }; const notebook: any = { widgets: [] as CodeCell[] }; const panel: any = { @@ -127,7 +128,7 @@ describe('OpenCodeCellActions', () => { const actions = new OpenCodeCellActions(cell); const btns = actions.node.querySelectorAll('button'); expect(btns.length).toBe(1); - expect(btns[0].textContent).toContain('🪄'); + expect(btns[0].textContent).toContain('AI'); }); it('disables the button when notebook panel cannot be resolved', () => { @@ -154,7 +155,7 @@ describe('OpenCodeCellActions', () => { const btn = actions.node.querySelector('button') as HTMLButtonElement; btn.click(); - const prompt = cell.node.querySelector( + const prompt = cell.inputArea!.node.querySelector( '.opencode-inline-prompt' ) as HTMLElement; expect(prompt).not.toBeNull(); @@ -169,7 +170,7 @@ describe('OpenCodeCellActions', () => { const btn = actions.node.querySelector('button') as HTMLButtonElement; btn.click(); btn.click(); - expect(cell.node.querySelector('.opencode-inline-prompt')).toBeNull(); + expect(cell.inputArea!.node.querySelector('.opencode-inline-prompt')).toBeNull(); }); it('disconnects model signals on dispose', () => { @@ -196,7 +197,7 @@ describe('OpenCodeCellActions', () => { const btn = actions.node.querySelector('button') as HTMLButtonElement; btn.click(); - const select = cell.node.querySelector( + const select = cell.inputArea!.node.querySelector( '.opencode-inline-prompt .opencode-model-select' ) as HTMLSelectElement; expect(select).not.toBeNull(); @@ -219,7 +220,7 @@ describe('OpenCodeCellActions', () => { btn.click(); expect( - cell.node.querySelector('.opencode-inline-prompt .opencode-model-select') + cell.inputArea!.node.querySelector('.opencode-inline-prompt .opencode-model-select') ).toBeNull(); }); }); diff --git a/src/components/opencode_cell_actions.ts b/src/components/opencode_cell_actions.ts index 14c8a4b..6c04bdc 100644 --- a/src/components/opencode_cell_actions.ts +++ b/src/components/opencode_cell_actions.ts @@ -121,7 +121,7 @@ export class OpenCodeCellActions extends Widget { this._hidePrompt(); } }); - Widget.attach(prompt, this._cell.node); + Widget.attach(prompt, this._cell.inputArea?.node ?? this._cell.node); this._prompt = prompt; }