From 0a52ad86d88cf28c0744b80e023793f86817e458 Mon Sep 17 00:00:00 2001 From: Valerii Kovalskii Date: Tue, 7 Apr 2026 20:15:57 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20resizable=20detail=20panel=20=E2=80=94?= =?UTF-8?q?=20drag=20left=20edge=20to=20resize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Drag handle on left edge of detail panel (blue highlight on hover) - Min 400px, max 90vw - Width saved in localStorage, restored on reload - Use transform:translateX for slide animation (works with any width) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/frontend/app.js | 35 +++++++++++++++++++++++++++++++++++ src/frontend/index.html | 1 + src/frontend/styles.css | 25 ++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/frontend/app.js b/src/frontend/app.js index 8fb269c..5861c1e 100644 --- a/src/frontend/app.js +++ b/src/frontend/app.js @@ -1636,6 +1636,41 @@ function closeDetail() { if (overlay) overlay.classList.remove('open'); } +// ── Detail panel resize ─────────────────────────────────────── +(function initDetailResize() { + var handle = document.getElementById('detailResizeHandle'); + var panel = document.getElementById('detailPanel'); + if (!handle || !panel) return; + + var startX, startW; + handle.addEventListener('mousedown', function(e) { + e.preventDefault(); + startX = e.clientX; + startW = panel.offsetWidth; + panel.classList.add('resizing'); + handle.classList.add('active'); + document.addEventListener('mousemove', onMove); + document.addEventListener('mouseup', onUp); + }); + function onMove(e) { + var newW = startW + (startX - e.clientX); + newW = Math.max(400, Math.min(newW, window.innerWidth * 0.9)); + panel.style.width = newW + 'px'; + panel.style.right = '0'; + } + function onUp() { + panel.classList.remove('resizing'); + handle.classList.remove('active'); + document.removeEventListener('mousemove', onMove); + document.removeEventListener('mouseup', onUp); + localStorage.setItem('codedash-detail-width', panel.style.width); + } + + // Restore saved width + var saved = localStorage.getItem('codedash-detail-width'); + if (saved) panel.style.width = saved; +})(); + async function loadGitCommits(project, fromTs, toTs) { try { var resp = await fetch('/api/git-commits?project=' + encodeURIComponent(project) + '&from=' + fromTs + '&to=' + toTs); diff --git a/src/frontend/index.html b/src/frontend/index.html index e3ae400..dfe59ba 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -131,6 +131,7 @@
+
Session Detail diff --git a/src/frontend/styles.css b/src/frontend/styles.css index 9f0fb8d..8b38066 100644 --- a/src/frontend/styles.css +++ b/src/frontend/styles.css @@ -729,17 +729,36 @@ body { .detail-panel { position: fixed; top: 0; - right: -700px; + right: 0; width: 700px; + min-width: 400px; + max-width: 90vw; height: 100vh; background: var(--bg-secondary); border-left: 1px solid var(--border); - transition: right 0.25s ease; + transform: translateX(100%); + transition: transform 0.25s ease; display: flex; flex-direction: column; z-index: 100; } -.detail-panel.open { right: 0; } +.detail-panel.open { transform: translateX(0); } +.detail-panel.resizing { transition: none; } + +.detail-resize-handle { + position: absolute; + left: -3px; + top: 0; + width: 6px; + height: 100%; + cursor: col-resize; + z-index: 101; +} +.detail-resize-handle:hover, +.detail-resize-handle.active { + background: var(--accent-blue); + opacity: 0.5; +} .detail-header { padding: 16px 20px;