Fix log panel overlap and hover-peek dismissal
The empty Changes state (flex:1 with no min-height:0) overflowed .main and drew over the log panel; add min-height:0/overflow clipping to .empty, .left and .main so the panel gets its own space. Make the status-bar log-peek use hover-intent (220ms delay + keep-open while hovering the popover) and sit flush above the bar so it can be moused into and scrolled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
16
src/App.tsx
16
src/App.tsx
@ -226,6 +226,9 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set
|
||||
const [logOpen, setLogOpen] = useState(false);
|
||||
const [peek, setPeek] = useState(false); // hover-over-loader log preview
|
||||
const logId = useRef(0);
|
||||
const peekTimer = useRef<number | null>(null);
|
||||
function showPeek() { if (peekTimer.current) { clearTimeout(peekTimer.current); peekTimer.current = null; } setPeek(true); }
|
||||
function hidePeek() { if (peekTimer.current) clearTimeout(peekTimer.current); peekTimer.current = window.setTimeout(() => setPeek(false), 220); }
|
||||
// resizable panels (persisted): left panel width + Get-Latest zone width
|
||||
const [leftW, setLeftW] = useState<number>(() => { const v = Number(localStorage.getItem("exd-left-w")); return v >= 280 ? v : 380; });
|
||||
const [syncW, setSyncW] = useState<number>(() => { const v = Number(localStorage.getItem("exd-sync-w")); return v >= 150 ? v : 220; });
|
||||
@ -634,13 +637,16 @@ function Workbench({ info, session, light, toggleTheme, lang, setLang, zoom, set
|
||||
|
||||
{logOpen && <LogPanel logs={logs} onClose={() => setLogOpen(false)} onClear={() => setLogs([])} />}
|
||||
|
||||
<div className="statusbar" onMouseEnter={() => setPeek(true)} onMouseLeave={() => setPeek(false)}>
|
||||
<span className={"stdot" + ((busy || scanning || !!pushing) ? " busy" : "")}>{(busy || scanning || !!pushing) ? <span className="ldr sm" /> : I.check}</span>
|
||||
<span className="stlast">{logs.length ? `${logs[logs.length - 1].cmd} ${logCount(logs[logs.length - 1])}` : "p4 — ready"}</span>
|
||||
<div className="statusbar">
|
||||
<span className="stfront" onMouseEnter={showPeek} onMouseLeave={hidePeek}>
|
||||
<span className={"stdot" + ((busy || scanning || !!pushing) ? " busy" : "")}>{(busy || scanning || !!pushing) ? <span className="ldr sm" /> : I.check}</span>
|
||||
<span className="stlast">{logs.length ? `${logs[logs.length - 1].cmd} ${logCount(logs[logs.length - 1])}` : "p4 — ready"}</span>
|
||||
</span>
|
||||
<button className="stlog" onClick={() => setLogOpen((o) => !o)} title="Ctrl+L">{I.log}<span>Log</span></button>
|
||||
{peek && logs.length > 0 && (
|
||||
<div className="logpeek">
|
||||
{logs.slice(-14).map((l) => <LogRow key={l.id} l={l} />)}
|
||||
<div className="logpeek" onMouseEnter={showPeek} onMouseLeave={hidePeek}>
|
||||
<div className="logpeek-h">{t("Log")} · {logs.length}</div>
|
||||
{logs.slice(-40).map((l) => <LogRow key={l.id} l={l} />)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user