feat: panneaux sticky + boutons close ✕
All checks were successful
CI / lint (push) Successful in 16s
CI / security (push) Successful in 9s
CI / test (push) Successful in 17s
CI / build (push) Successful in 16s

This commit is contained in:
Bruno Charest 2026-05-30 08:00:50 -04:00
parent de9f4b0bb5
commit a8131a4285
2 changed files with 25 additions and 12 deletions

View File

@ -724,11 +724,15 @@
</div>
<div class="editor-body" style="flex:1;overflow:hidden;position:relative;padding:0">
<canvas id="graph-canvas" style="width:100%;height:100%;cursor:grab"></canvas>
<!-- Info panel: top-right, shows on hover -->
<div id="graph-info-panel" style="display:none;position:absolute;top:10px;right:10px;max-width:320px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;padding:12px 14px;font-size:0.78rem;color:var(--text-primary);z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.4);pointer-events:none">
<!-- Info panel: top-right, shows on hover, stays until closed -->
<div id="graph-info-panel" style="display:none;position:absolute;top:10px;right:10px;max-width:320px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:8px;padding:12px 14px;font-size:0.78rem;color:var(--text-primary);z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.4)">
<button id="graph-info-close" style="position:absolute;top:6px;right:8px;background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:1rem;line-height:1;padding:2px" title="Fermer"></button>
<div id="graph-info-content"></div>
</div>
<!-- Preview panel: right sidebar, full height, shows on Ctrl+hover -->
<div id="graph-preview-panel" style="display:none;position:absolute;top:0;right:0;width:380px;height:100%;background:var(--bg-primary);border-left:1px solid var(--border-color);z-index:9;overflow-y:auto;padding:16px;font-size:0.8rem;color:var(--text-primary);box-shadow:-4px 0 16px rgba(0,0,0,0.3)">
<!-- Preview panel: right sidebar, full height, shows on Ctrl+hover, stays until closed -->
<div id="graph-preview-panel" style="display:none;position:absolute;top:0;right:0;width:380px;height:100%;background:var(--bg-primary);border-left:1px solid var(--border-color);z-index:9;overflow-y:auto;font-size:0.8rem;color:var(--text-primary);box-shadow:-4px 0 16px rgba(0,0,0,0.3)">
<button id="graph-preview-close" style="position:sticky;top:0;float:right;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-muted);cursor:pointer;font-size:0.9rem;padding:2px 8px;z-index:1;margin-bottom:-24px" title="Fermer">✕ Fermer</button>
<div id="graph-preview-content" style="padding:16px;padding-top:8px"></div>
</div>
<!-- Status bar + legend -->
<div style="position:absolute;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;padding:4px 12px;background:var(--bg-primary);border-top:1px solid var(--border-color);font-size:0.7rem;color:var(--text-muted)">

View File

@ -53,7 +53,9 @@ export const GraphViewManager = {
_tagFilter: '',
_hoveredNode: null,
_infoPanel: null,
_infoContent: null,
_previewPanel: null,
_previewContent: null,
_previewCache: {},
_previewPending: null,
_ctrlHoverNode: null,
@ -71,7 +73,9 @@ export const GraphViewManager = {
if (!modal || !canvas) return;
this._infoPanel = document.getElementById('graph-info-panel');
this._infoContent = document.getElementById('graph-info-content');
this._previewPanel = document.getElementById('graph-preview-panel');
this._previewContent = document.getElementById('graph-preview-content');
this._depth = depthSlider ? parseInt(depthSlider.value) : 1;
this._scope = 'directory';
@ -535,7 +539,7 @@ export const GraphViewManager = {
_showTooltip(node, screenX, screenY, isPreview) {
if (isPreview) return; // Handled by _showPreviewTooltip
if (!this._infoPanel) return;
if (!this._infoContent) return;
const cacheKey = `${this._vault}:${node.path}`;
const cached = this._previewCache[cacheKey];
const meta = cached?.meta;
@ -558,8 +562,8 @@ export const GraphViewManager = {
const typeIcon = node.type === 'directory' ? '📁' : '📄';
const typeLabel = node.type === 'directory' ? 'Dossier' : (node.path || '').endsWith('.md') ? 'Markdown' : 'Fichier';
this._infoPanel.innerHTML = `
<div style="display:flex;align-items:flex-start;gap:8px;margin-bottom:8px">
this._infoContent.innerHTML = `
<div style="display:flex;align-items:flex-start;gap:8px;margin-bottom:8px;padding-right:16px">
<span style="font-size:1.2rem">${typeIcon}</span>
<div style="flex:1;min-width:0">
<div style="font-weight:600;font-size:0.85rem;word-break:break-word">${meta?.title || node.name}</div>
@ -578,12 +582,11 @@ export const GraphViewManager = {
},
_hideTooltip() {
if (this._infoPanel) this._infoPanel.style.display = 'none';
if (this._previewPanel) this._previewPanel.style.display = 'none';
// Panels are now sticky — only hide via close button
},
_showPreviewTooltip(node, preview, screenX, screenY) {
if (!this._previewPanel || this._ctrlHoverNode !== node) return;
if (!this._previewContent || this._ctrlHoverNode !== node) return;
const cacheKey = `${this._vault}:${node.path}`;
const cached = this._previewCache[cacheKey];
const meta = cached?.meta;
@ -600,7 +603,7 @@ export const GraphViewManager = {
if (items.length > 0) fmSummary = `<div style="font-size:0.7rem;color:var(--text-muted);margin:4px 0">${items.join(' · ')}</div>`;
}
const tags = (meta?.tags || node.tags || []).slice(0, 8);
this._previewPanel.innerHTML = `
this._previewContent.innerHTML = `
<div style="font-weight:700;font-size:0.95rem;margin-bottom:4px;word-break:break-word">${meta?.title || node.name}</div>
<div style="color:var(--text-muted);font-size:0.7rem;margin-bottom:6px;word-break:break-all">${node.path}</div>
${fmSummary}
@ -843,7 +846,7 @@ export function initGraphView() {
gm._dragNode = null;
gm._panning = false;
canvas.style.cursor = 'grab';
gm._hideTooltip();
// Panels stay visible until closed via button
});
canvas.addEventListener('wheel', (e) => gm._onWheel(e), { passive: false });
window.addEventListener('resize', () => gm._onResize());
@ -854,4 +857,10 @@ export function initGraphView() {
gm.close();
}
});
// Close buttons for sticky panels
const infoClose = document.getElementById('graph-info-close');
if (infoClose) infoClose.addEventListener('click', () => { if (gm._infoPanel) gm._infoPanel.style.display = 'none'; });
const previewClose = document.getElementById('graph-preview-close');
if (previewClose) previewClose.addEventListener('click', () => { if (gm._previewPanel) gm._previewPanel.style.display = 'none'; });
}