Make autoscroll behaviour more intuitive (#143)

* Fix editor shift

* Make autoscrolling more intuitive
This commit is contained in:
Jonatan Kłosko 2021-04-05 15:06:14 +02:00 committed by GitHub
parent 7d1d1f4d98
commit 70be004ee0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 10 deletions

View file

@ -3,6 +3,7 @@ import LiveEditor from "./live_editor";
import Markdown from "./markdown";
import { globalPubSub } from "../lib/pub_sub";
import { smoothlyScrollToElement } from "../lib/utils";
import scrollIntoView from "scroll-into-view-if-needed";
/**
* A hook managing a single cell.
@ -127,11 +128,24 @@ function handleInsertModeChanged(hook, insertMode) {
if (hook.state.isFocused) {
hook.state.insertMode = insertMode;
if (hook.state.liveEditor) {
if (hook.state.insertMode) {
hook.state.liveEditor && hook.state.liveEditor.focus();
smoothlyScrollToElement(hook.el);
hook.state.liveEditor.focus();
// The insert mode may be enabled as a result of clicking the editor,
// in which case we want to wait until editor handles the click
// and sets new cursor position.
// To achieve this, we simply put this task at the end of event loop,
// ensuring all click handlers are executed first.
setTimeout(() => {
scrollIntoView(document.activeElement, {
scrollMode: "if-needed",
behavior: "smooth",
block: "center",
});
}, 0);
} else {
hook.state.liveEditor && hook.state.liveEditor.blur();
hook.state.liveEditor.blur();
}
}
}
}

View file

@ -41,5 +41,11 @@ export function selectElementContent(element) {
}
export function smoothlyScrollToElement(element) {
const { height } = element.getBoundingClientRect();
if (height < window.innerHeight) {
element.scrollIntoView({ behavior: "smooth", block: "center" });
} else {
element.scrollIntoView({ behavior: "smooth", block: "start" });
}
}

View file

@ -17,7 +17,8 @@
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
"remixicon": "^2.5.0"
"remixicon": "^2.5.0",
"scroll-into-view-if-needed": "^2.2.28"
},
"devDependencies": {
"@babel/core": "^7.0.0",
@ -43,7 +44,7 @@
}
},
"../deps/phoenix": {
"version": "1.5.7",
"version": "1.5.8",
"license": "MIT"
},
"../deps/phoenix_html": {
@ -3722,6 +3723,11 @@
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
},
"node_modules/compute-scroll-into-view": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
"integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -13423,6 +13429,14 @@
"node": ">= 8.9.0"
}
},
"node_modules/scroll-into-view-if-needed": {
"version": "2.2.28",
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.28.tgz",
"integrity": "sha512-8LuxJSuFVc92+0AdNv4QOxRL4Abeo1DgLnGNkn1XlaujPH/3cCFz3QI60r2VNu4obJJROzgnIUw5TKQkZvZI1w==",
"dependencies": {
"compute-scroll-into-view": "^1.0.17"
}
},
"node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@ -18942,6 +18956,11 @@
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
},
"compute-scroll-into-view": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz",
"integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -26819,6 +26838,14 @@
"ajv-keywords": "^3.5.2"
}
},
"scroll-into-view-if-needed": {
"version": "2.2.28",
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.28.tgz",
"integrity": "sha512-8LuxJSuFVc92+0AdNv4QOxRL4Abeo1DgLnGNkn1XlaujPH/3cCFz3QI60r2VNu4obJJROzgnIUw5TKQkZvZI1w==",
"requires": {
"compute-scroll-into-view": "^1.0.17"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",

View file

@ -22,7 +22,8 @@
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
"remixicon": "^2.5.0"
"remixicon": "^2.5.0",
"scroll-into-view-if-needed": "^2.2.28"
},
"devDependencies": {
"@babel/core": "^7.0.0",

View file

@ -146,7 +146,7 @@ defmodule LivebookWeb.SessionLive.CellComponent do
defp render_editor(assigns) do
~L"""
<div class="py-3 rounded-lg overflow-hidden bg-editor relative">
<div class="py-3 rounded-lg bg-editor relative">
<div
id="editor-container-<%= @cell_view.id %>"
data-element="editor-container"