Skip to content

Commit

Permalink
Re-focus input after modifying model, keep input for 0.5s
Browse files Browse the repository at this point in the history
  • Loading branch information
krassowski committed Dec 1, 2023
1 parent aa845bf commit 77476a7
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 3 deletions.
39 changes: 36 additions & 3 deletions packages/outputarea/src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ const OUTPUT_AREA_OUTPUT_CLASS = 'jp-OutputArea-output';
*/
const OUTPUT_AREA_PROMPT_CLASS = 'jp-OutputArea-prompt';

const OUTPUT_AREA_STDIN_HIDING_CLASS = 'jp-OutputArea-stdin-hiding';

/**
* The class name added to OutputPrompt.
*/
Expand Down Expand Up @@ -457,10 +459,11 @@ export class OutputArea extends Widget {
if (this.model.length >= this.maxNumberOutputs) {
this.maxNumberOutputs = this.model.length;
}
this.layout.addWidget(panel);

this._inputRequested.emit(input);

// Get the input node to ensure focus after updating the model upon user reply.
const inputNode = input.node.getElementsByTagName('input')[0];

/**
* Wait for the stdin to complete, add it to the model (so it persists)
* and remove the stdin widget.
Expand All @@ -470,14 +473,37 @@ export class OutputArea extends Widget {
if (this.model.length >= this.maxNumberOutputs) {
this.maxNumberOutputs = this.model.length + 1;
}
panel.addClass(OUTPUT_AREA_STDIN_HIDING_CLASS);
// Use stdin as the stream so it does not get combined with stdout.
// Note: because it modifies DOM it may (will) shift focus away from the input node.
this.model.add({
output_type: 'stream',
name: 'stdin',
text: value + '\n'
});
panel.dispose();
// Refocus the input node after it lost focus due to update of the model.
inputNode.focus();

// Keep the input in view for a little while; this (along refocusing)
// ensures that we can avoid the cell editor stealing the focus, and
// leading to user inadvertently modifying editor content when executing
// consecutive commands in short succession.
window.setTimeout(() => {
// Tack currently focused element to ensure that it remains on it
// after disposal of the panel with the old input
// (which modifies DOM and can lead to focus jump).
const focusedElement = document.activeElement;
// Dispose the old panel with no longer needed input box.
panel.dispose();
// Refocus the element that was focused before.
if (focusedElement && focusedElement instanceof HTMLElement) {
focusedElement.focus();
}
}, 500);
});

// Note: the `input.value` promise must be listened to before we attach the panel
this.layout.addWidget(panel);
}

/**
Expand Down Expand Up @@ -1093,6 +1119,11 @@ export class Stdin extends Widget implements IStdin {
* not be called directly by user code.
*/
handleEvent(event: KeyboardEvent): void {
if (this._resolved) {
// Do not handle any more key events if the promise was resolved.
event.preventDefault();
return;
}
const input = this._input;

if (event.type === 'keydown') {
Expand All @@ -1112,6 +1143,7 @@ export class Stdin extends Widget implements IStdin {
this._value += input.value;
Stdin._historyPush(this._historyKey, input.value);
}
this._resolved = true;
this._promise.resolve(void 0);
} else if (event.key === 'Escape') {
// currently this gets clobbered by the documentsearch:end command at the notebook level
Expand Down Expand Up @@ -1227,6 +1259,7 @@ export class Stdin extends Widget implements IStdin {
private _trans: TranslationBundle;
private _value: string;
private _valueCache: string;
private _resolved: boolean = false;
}

export namespace Stdin {
Expand Down
31 changes: 31 additions & 0 deletions packages/outputarea/style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,37 @@ body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated::before {
opacity: 1;
}

.jp-OutputArea-stdin-hiding:has(~ .jp-OutputArea-stdin-item) {
/* hide the old input immediately if a new input was attached */
display: none;
}

.jp-OutputArea-stdin-hiding .jp-Stdin-prompt::after {
content: '✓';
color: var(--jp-accent-color0);
font-weight: bold;
animation: jp-reveal-check 0.1s forwards;
font-size: 120%;
}

@keyframes jp-reveal-check {
0% {
transform: scale(0.5);
opacity: 0;
}

100% {
transform: scale(1);
opacity: 1;
}
}

.jp-OutputArea-stdin-hiding {
opacity: 0;
transition: opacity 0.1s ease-in;
transition-delay: 0.3s;
}

/*-----------------------------------------------------------------------------
| Output Area View
|----------------------------------------------------------------------------*/
Expand Down

0 comments on commit 77476a7

Please sign in to comment.