mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-07 10:16:03 -10:00
fix(editor): keep tooltips full width at the editor's right edge (#1203)
On WebKit, CodeMirror positions tooltips absolutely inside the editor, but the tooltip space still reported the whole window as the right bound. CodeMirror never shifted a tooltip near the editor's right edge to the left, the box was squeezed into the space left of that edge, and the next measurement read the squeezed width, so it could end as a one-character column. The tooltip space is now the editor's own horizontal extent (clamped to the window) and tooltips size to their content, which fixes hover, inline blame, debugger values, signature help and hints together. Co-authored-by: ntbang0901 <[email protected]>
This commit is contained in:
1 parent
bdc108a61b
commit
8f77d7077c
3 files changed
+43
-8
No files matched your search
@@ -319,15 +319,23 @@ export interface SetupOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltips (hints, docs, completion) stay below the editor's top edge: one
|
||||
* above the first lines flips below them instead of hiding under the tabs.
|
||||
* Tooltips (hints, docs, completion) stay inside the editor horizontally and
|
||||
* below its top edge. WebKit positions them `absolute` within `.cm-editor`, so
|
||||
* a window-wide right bound makes CodeMirror skip the shift left and the
|
||||
* browser squeezes the box into the space left of the editor's edge.
|
||||
*/
|
||||
const tooltipSpace = tooltips({
|
||||
tooltipSpace: (view) => {
|
||||
const top = view.scrollDOM.getBoundingClientRect().top;
|
||||
return { top, left: 0, right: window.innerWidth, bottom: window.innerHeight };
|
||||
},
|
||||
});
|
||||
export function tooltipBounds(view: { scrollDOM: Element; dom: Element }) {
|
||||
const { top } = view.scrollDOM.getBoundingClientRect();
|
||||
const { left, right } = view.dom.getBoundingClientRect();
|
||||
return {
|
||||
top,
|
||||
left: Math.max(0, left),
|
||||
right: Math.min(window.innerWidth, right),
|
||||
bottom: window.innerHeight,
|
||||
};
|
||||
}
|
||||
|
||||
const tooltipSpace = tooltips({ tooltipSpace: tooltipBounds });
|
||||
|
||||
export function baseExtensions(o: SetupOptions): Extension {
|
||||
return [
|
||||
|
||||
@@ -248,6 +248,9 @@ export const openideaTheme = EditorView.theme({
|
||||
|
||||
// Overlays
|
||||
".cm-tooltip": {
|
||||
// Natural width, so a measurement taken while squeezed is not fed back (#1188).
|
||||
width: "max-content",
|
||||
maxWidth: "100%",
|
||||
backgroundColor: "var(--bg-popup)",
|
||||
color: "var(--fg)",
|
||||
border: "1px solid var(--border-popup)",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { tooltipBounds } from "./setup";
|
||||
|
||||
const el = (r: Partial<DOMRect>) => ({ getBoundingClientRect: () => r as DOMRect }) as Element;
|
||||
const original = window.innerWidth;
|
||||
|
||||
beforeEach(() => {
|
||||
Object.defineProperty(window, "innerWidth", { value: 1200, configurable: true });
|
||||
});
|
||||
afterEach(() => {
|
||||
Object.defineProperty(window, "innerWidth", { value: original, configurable: true });
|
||||
});
|
||||
|
||||
describe("tooltipBounds", () => {
|
||||
it.each([
|
||||
["editor flush with the right edge", { left: 300, right: 1200 }, 300, 1200],
|
||||
["narrow split pane", { left: 0, right: 400 }, 0, 400],
|
||||
["editor in the middle", { left: 250, right: 750 }, 250, 750],
|
||||
["editor spilling outside the window", { left: -20, right: 1500 }, 0, 1200],
|
||||
])("%s", (_, rect, left, right) => {
|
||||
const b = tooltipBounds({ scrollDOM: el({ top: 80 }), dom: el(rect) });
|
||||
expect(b).toMatchObject({ top: 80, left, right });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user