Fix Term Widget not registering pointer events (#1614)

This is a bit janky. The problem is that we were placing the
`xterm-viewport` div, which contains the scroll observer for the xterm
contents, at a higher z-index than the xterm contents, meaning that the
contents couldn't register any pointer events. If we don't put a
z-index, though, the scroll bar can't accept pointer events. To get
around this, I've added two observer divs, which control whether the
contents or the viewport have pointer event priority. The first div, the
`term-scrollbar-show-observer`, sits above where the scrollbar will be
rendered. When the user hovers over it, it will cause the viewport div
to move to a z-index above the contents. It will also enable a second
div, the `term-scrollbar-hide-observer`, which sits above the viewport
and the term contents, but not blocking the scrollbar. When the user
hovers over this div (indicating their mouse has left the scrollbar),
the viewport div is moved back to its original z-index and the hide
observer is set to `display: none`. This gives pointer event priority
back to the contents div.

This resolves an issue where the user could not click links in the
terminal output.

Resolves #1357
This commit is contained in:
Evan Simkowitz 2024-12-23 23:35:51 -05:00 committed by GitHub
parent b778417b9b
commit b7a5dea0a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 20 deletions

View File

@ -36,23 +36,23 @@
overflow: hidden;
}
.term-cmd-toolbar {
display: flex;
flex-direction: row;
height: 24px;
border-bottom: 1px solid var(--border-color);
overflow: hidden;
align-items: center;
.term-cmd-toolbar {
display: flex;
flex-direction: row;
height: 24px;
border-bottom: 1px solid var(--border-color);
overflow: hidden;
align-items: center;
.term-cmd-toolbar-text {
font: var(--fixed-font);
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0 5px;
}
}
.term-cmd-toolbar-text {
font: var(--fixed-font);
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0 5px;
}
}
.term-connectelem {
flex-grow: 1;
@ -126,10 +126,27 @@
}
}
.term-scrollbar-show-observer {
z-index: calc(var(--zindex-xterm-viewport-overlay) - 1);
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 12px;
}
.term-scrollbar-hide-observer {
z-index: calc(var(--zindex-xterm-viewport-overlay) + 1);
display: none;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: calc(100% - 12px);
}
.terminal {
.xterm-viewport {
z-index: var(--zindex-xterm-viewport-overlay);
&::-webkit-scrollbar {
width: 6px;
height: 6px;

View File

@ -848,7 +848,19 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
termModeRef.current = termMode;
}, [termMode]);
let stickerConfig = {
const scrollbarHideObserverRef = React.useRef<HTMLDivElement>(null);
const onScrollbarShowObserver = React.useCallback(() => {
const termViewport = viewRef.current.getElementsByClassName("xterm-viewport")[0] as HTMLDivElement;
termViewport.style.zIndex = "var(--zindex-xterm-viewport-overlay)";
scrollbarHideObserverRef.current.style.display = "block";
}, []);
const onScrollbarHideObserver = React.useCallback(() => {
const termViewport = viewRef.current.getElementsByClassName("xterm-viewport")[0] as HTMLDivElement;
termViewport.style.zIndex = "auto";
scrollbarHideObserverRef.current.style.display = "none";
}, []);
const stickerConfig = {
charWidth: 8,
charHeight: 16,
rows: model.termRef.current?.terminal.rows ?? 24,
@ -862,7 +874,14 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
<TermStickers config={stickerConfig} />
<TermToolbarVDomNode key="vdom-toolbar" blockId={blockId} model={model} />
<TermVDomNode key="vdom" blockId={blockId} model={model} />
<div key="conntectElem" className="term-connectelem" ref={connectElemRef}></div>
<div key="conntectElem" className="term-connectelem" ref={connectElemRef}>
<div className="term-scrollbar-show-observer" onPointerOver={onScrollbarShowObserver} />
<div
ref={scrollbarHideObserverRef}
className="term-scrollbar-hide-observer"
onPointerOver={onScrollbarHideObserver}
/>
</div>
</div>
);
};