1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

ui/ux: improved handling editor's focus when interacting with <Dock/>

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-10-09 21:34:36 +03:00
parent 118d07cfb9
commit d7006e63ea
2 changed files with 36 additions and 5 deletions

View File

@ -22,11 +22,13 @@
import "./dock-tab-content.scss";
import React from "react";
import { disposeOnUnmount, observer } from "mobx-react";
import { computed, makeObservable, observable, reaction } from "mobx";
import { action, computed, makeObservable, observable, reaction } from "mobx";
import type { DockTab, TabId } from "./dock.store";
import { dockStore } from "./dock.store";
import { cssNames } from "../../utils";
import { DockTabComponents, dockViewsManager } from "./dock.views-manager";
import { MonacoEditor } from "../monaco-editor";
import throttle from "lodash/throttle";
export interface DockTabContentProps extends React.HTMLAttributes<any> {
className?: string;
@ -36,12 +38,20 @@ export interface DockTabContentProps extends React.HTMLAttributes<any> {
@observer
export class DockTabContent extends React.Component<DockTabContentProps> {
@observable.ref editor: MonacoEditor;
constructor(props: DockTabContentProps) {
super(props);
makeObservable(this);
disposeOnUnmount(this, [
reaction(() => this.tabId, () => this.error = ""), // reset
reaction(() => this.tabId, this.onTabChange, { delay: 100 }),
// keep focus on editor's area when <Dock/> just opened
reaction(() => dockStore.isOpen, isOpen => isOpen && this.focusEditor()),
// focus to editor on dock's resize or turning into fullscreen mode
dockStore.onResize(throttle(() => this.focusEditor(), 250)),
]);
}
@ -55,6 +65,22 @@ export class DockTabContent extends React.Component<DockTabContentProps> {
@observable error = "";
@computed get editorIsVisible() {
return Boolean(this.tabComponents.editor);
}
focusEditor() {
if (!this.editorIsVisible) return;
this.editor.focus();
}
@action
onTabChange = () => {
this.error = ""; // reset any errors from another tab
this.focusEditor(); // focus to editor if available via registered tab views
};
/**
* Always keep editor in DOM while (while <Dock/> is open/rendered).
* This allows to restore editor's model-view state (cursor pos, selection, etc.)
@ -62,20 +88,21 @@ export class DockTabContent extends React.Component<DockTabContentProps> {
*/
renderEditor() {
const { tabId, tabComponents: { editor } } = this;
const isHidden = !editor;
return (
<MonacoEditor
id={tabId}
className={cssNames({ hidden: isHidden })}
autoFocus={true}
className={cssNames({ hidden: !this.editorIsVisible })}
value={editor?.getValue(tabId) ?? ""}
onChange={value => {
this.error = "";
editor?.setValue(tabId, value);
}}
onError={error => {
this.error = isHidden ? "" : error;
this.error = this.editorIsVisible ? error : "";
}}
ref={editor => this.editor = editor}
/>
);
}

View File

@ -238,6 +238,10 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
return this.editor?.getValue(opts) ?? "";
}
focus(){
this.editor?.focus();
}
@action
validate = async (value = this.getValue()): Promise<void> => {
const { language } = this.props;