fix: attach inline prompt to cell.inputArea (under the editor), not cell.node

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 <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-07-23 17:54:07 +08:00
co-authored by Claude Fable 5
parent df2f3dff95
commit 8ed55c43c7
2 changed files with 7 additions and 6 deletions
+6 -5
View File
@@ -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();
});
});
+1 -1
View File
@@ -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;
}