mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
fix(ui): wrap long tooltip text inside the bubble (#983)
Hovering an editor tab with a long path showed a tooltip whose text ran past the bubble: tooltips never wrapped (`white-space: nowrap`) and were capped at 360px. Tooltip text now wraps inside the bubble, breaking long paths where needed, and the shortcut stays on one line next to it. The bubble grows up to 720px or the window width less 32px, so most paths still fit on one line. Short tooltips look as before (same size and line height), and newlines in tooltip text are still collapsed. Fixes #968. Co-authored-by: yangyezhuang <68811197+yangyezhuang@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
max-width: 360px;
|
||||
max-width: min(720px, calc(100vw - 32px));
|
||||
padding: 6px 10px;
|
||||
border-radius: var(--radius-tooltip, 6px);
|
||||
background: var(--bg-tooltip);
|
||||
@@ -15,17 +15,23 @@
|
||||
font-size: var(--fs-ui);
|
||||
line-height: 16px;
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
}
|
||||
.tooltip[data-placed] {
|
||||
opacity: 1;
|
||||
transition: opacity var(--dur-fast) var(--ease);
|
||||
}
|
||||
/* Long paths wrap inside the bubble; the shortcut stays on one line. */
|
||||
.text {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.shortcut {
|
||||
font-family: var(--font-keys);
|
||||
font-size: var(--fs-ui);
|
||||
color: color-mix(in srgb, var(--fg-tooltip) 62%, transparent);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { act, cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { TOOLTIP_DELAY, TooltipHost, tooltipAttrs } from "./Tooltip";
|
||||
import styles from "./Tooltip.module.css";
|
||||
|
||||
describe("tooltipAttrs", () => {
|
||||
it("returns empty object when text is missing", () => {
|
||||
expect(tooltipAttrs(undefined)).toEqual({});
|
||||
expect(tooltipAttrs("")).toEqual({});
|
||||
});
|
||||
|
||||
it("sets data-tooltip and optional shortcut", () => {
|
||||
expect(tooltipAttrs("Close Tab")).toEqual({ "data-tooltip": "Close Tab" });
|
||||
expect(tooltipAttrs("Save All", "Ctrl+S")).toEqual({
|
||||
"data-tooltip": "Save All",
|
||||
"data-tooltip-shortcut": "Ctrl+S",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("TooltipHost", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("shows tooltip text with styles.text class and shortcut after delay", async () => {
|
||||
render(
|
||||
<div>
|
||||
<TooltipHost />
|
||||
<button type="button" {...tooltipAttrs("d:/project/src/main.rs", "Ctrl+Shift+S")}>
|
||||
Tab
|
||||
</button>
|
||||
</div>,
|
||||
);
|
||||
|
||||
const button = screen.getByRole("button", { name: "Tab" });
|
||||
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||
|
||||
fireEvent.pointerOver(button);
|
||||
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(TOOLTIP_DELAY);
|
||||
});
|
||||
|
||||
const tooltip = screen.getByRole("tooltip");
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
expect(tooltip).toHaveClass(styles.tooltip!);
|
||||
|
||||
const textSpan = tooltip.querySelector(`.${styles.text!}`);
|
||||
expect(textSpan).toBeInTheDocument();
|
||||
expect(textSpan?.textContent).toBe("d:/project/src/main.rs");
|
||||
|
||||
const shortcutSpan = tooltip.querySelector(`.${styles.shortcut!}`);
|
||||
expect(shortcutSpan).toBeInTheDocument();
|
||||
expect(shortcutSpan?.textContent).toBe("Ctrl+Shift+S");
|
||||
|
||||
// Pointer out hides the tooltip
|
||||
fireEvent.pointerOut(button);
|
||||
expect(screen.queryByRole("tooltip")).toBeNull();
|
||||
});
|
||||
});
|
||||
+1
-1
@@ -121,7 +121,7 @@ export function TooltipHost() {
|
||||
data-placed={shown.placed || undefined}
|
||||
style={{ left: shown.x, top: shown.y }}
|
||||
>
|
||||
<span>{shown.text}</span>
|
||||
<span className={styles.text}>{shown.text}</span>
|
||||
{shown.shortcut && <span className={styles.shortcut}>{shown.shortcut}</span>}
|
||||
</div>,
|
||||
document.body,
|
||||
|
||||
Reference in New Issue
Block a user