Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Commit c01bee2

Browse files
committed
feat: add draggable sidebar resizer
- Add a thin drag handle on the right edge of the sidebar - Drag to resize between 180px and 600px - Width persists across page loads via localStorage - Resizer highlights on hover/drag with accent color - Hidden on mobile where sidebar is off-screen by default
1 parent 1a7a4ce commit c01bee2

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

public/css/style.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,27 @@ cap-widget {
467467
transition: transform var(--transition);
468468
}
469469

470+
.sidebar.resizing {
471+
transition: none;
472+
}
473+
474+
.sidebar-resizer {
475+
position: absolute;
476+
top: 0;
477+
right: 0;
478+
bottom: 0;
479+
width: 5px;
480+
cursor: col-resize;
481+
z-index: 10;
482+
background: transparent;
483+
transition: background 0.15s;
484+
}
485+
486+
.sidebar-resizer:hover,
487+
.sidebar.resizing .sidebar-resizer {
488+
background: var(--accent-1);
489+
}
490+
470491
.main-content {
471492
position: relative;
472493
z-index: 1;
@@ -1082,6 +1103,10 @@ tbody tr:hover {
10821103
transform: translateX(0);
10831104
}
10841105

1106+
.sidebar-resizer {
1107+
display: none;
1108+
}
1109+
10851110
.main-content {
10861111
margin-left: 0;
10871112
padding: 20px;

public/js/app.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,51 @@ async function handleRegister(e) {
355355
}
356356
}
357357

358+
function initSidebarResize() {
359+
const sidebar = $('#sidebar');
360+
const resizer = $('#sidebar-resizer');
361+
if (!sidebar || !resizer) return;
362+
363+
const saved = localStorage.getItem('zh_sidebar_width');
364+
if (saved) {
365+
const w = parseInt(saved, 10);
366+
if (w >= 180 && w <= 600) {
367+
sidebar.style.width = w + 'px';
368+
sidebar.style.setProperty('--sidebar-w', w + 'px');
369+
document.querySelector('.main-content').style.marginLeft = w + 'px';
370+
}
371+
}
372+
373+
let startX, startW;
374+
375+
function onMouseDown(e) {
376+
startX = e.clientX;
377+
startW = sidebar.getBoundingClientRect().width;
378+
sidebar.classList.add('resizing');
379+
document.documentElement.style.userSelect = 'none';
380+
document.addEventListener('mousemove', onMouseMove);
381+
document.addEventListener('mouseup', onMouseUp);
382+
}
383+
384+
function onMouseMove(e) {
385+
const w = Math.min(600, Math.max(180, startW + e.clientX - startX));
386+
sidebar.style.width = w + 'px';
387+
sidebar.style.setProperty('--sidebar-w', w + 'px');
388+
document.querySelector('.main-content').style.marginLeft = w + 'px';
389+
}
390+
391+
function onMouseUp() {
392+
sidebar.classList.remove('resizing');
393+
document.documentElement.style.userSelect = '';
394+
document.removeEventListener('mousemove', onMouseMove);
395+
document.removeEventListener('mouseup', onMouseUp);
396+
const w = sidebar.getBoundingClientRect().width;
397+
localStorage.setItem('zh_sidebar_width', Math.round(w));
398+
}
399+
400+
resizer.addEventListener('mousedown', onMouseDown);
401+
}
402+
358403
// ===== DASHBOARD =====
359404
async function renderDashboard() {
360405
const app = $('#app');
@@ -415,6 +460,7 @@ async function renderDashboard() {
415460
</div>
416461
<div style="padding:4px 0 8px;text-align:center;font-size:0.7rem;color:var(--text-muted);letter-spacing:0.05em">v0.9.8 BETA</div>
417462
</div>
463+
<div class="sidebar-resizer" id="sidebar-resizer"></div>
418464
</aside>
419465
420466
<button class="hamburger-toggle" id="hamburger-toggle" aria-label="Toggle menu">
@@ -463,6 +509,8 @@ async function renderDashboard() {
463509
$('#sidebar').classList.toggle('open');
464510
});
465511

512+
initSidebarResize();
513+
466514
const page = window.location.pathname.replace('/', '') || 'overview';
467515
navigateTo(page);
468516
}

0 commit comments

Comments
 (0)