refactor(sidebar): unify left sidebar panel sizing and resize logic

Replace per-panel height constants, state, loaders and resize handlers with a single
model for all left sidebar panels. Panel sizes are now stored/read as a JSON
object under "gitlite.sidebarPanelHeights.v2" and managed via shared helpers.

Key changes and behavior:
- Introduce SIDEBAR_PANEL_ORDER, per-panel MIN/DEFAULT heights and a shared MAX/STEP.
- Single in-memory map sidebarPanelHeights with clamp/load/persist helpers.
- One pointer/keyboard resize flow: startSidebarPanelResize, onSidebarPanelResizeMove,
  endSidebarPanelResize and onSidebarPanelResizeKeydown. Dragging moves the border
  between the panel above (grows) and the next expanded panel below (shrinks).
  The last expanded panel is flexible (1fr) and follows automatically.
- Double-click on a handle resets the above/below panels to their defaults.
- buildLeftSidebarRows now derives grid rows from the unified state; template uses
  new handlers and aria attributes.
- LocalStorage remains best-effort; persistence failures are ignored as before.

Removes many duplicate functions/variables for individual panels and simplifies
the UI logic for showing/hiding resize handles and resizing behavior.
This commit is contained in:
2026-09-17 22:45:20 +02:00
parent e7303116a3
commit 8c99e15dc9
2 changed files with 249 additions and 351 deletions
+9 -80
View File
@@ -1713,16 +1713,18 @@
}
.left-sidebar {
/* The row template is built in App.svelte from the panel heights. */
display: grid;
grid-template-rows: minmax(180px, var(--branch-panel-height, 260px)) 14px minmax(150px, var(--stash-panel-height, 190px)) 14px minmax(220px, 1fr);
align-content: start;
min-width: 0;
min-height: 0;
gap: 0;
overflow-x: hidden;
overflow-y: auto;
}
.left-panel-resize-handle {
min-height: 14px;
min-height: 8px;
margin: 0;
}
@@ -1732,34 +1734,12 @@
min-width: 0;
}
.left-sidebar.branch-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 190px)) 14px minmax(220px, 1fr);
}
.left-sidebar.explorer-collapsed {
grid-template-rows: minmax(180px, var(--branch-panel-height, 260px)) 14px minmax(150px, var(--stash-panel-height, 190px)) 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 190px)) 0 auto;
}
.left-sidebar:has(.stash-panel.collapsed) {
grid-template-rows: minmax(180px, var(--branch-panel-height, 260px)) 14px auto 0 minmax(220px, 1fr);
}
.left-sidebar.branch-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 minmax(220px, 1fr);
}
.left-sidebar.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: minmax(180px, var(--branch-panel-height, 260px)) 14px auto 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 auto;
align-content: start;
}
/* --- Main panel --- */
@@ -7508,31 +7488,6 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
.history-aside { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr); row-gap: 0; }
.history-resize-handle { display: none; }
.shell-body { gap: 6px; }
.left-sidebar {
grid-template-rows: minmax(180px, var(--branch-panel-height, 230px)) 14px minmax(150px, var(--stash-panel-height, 170px)) 14px minmax(220px, 1fr);
}
.left-sidebar:has(.stash-panel.collapsed) {
grid-template-rows: minmax(180px, var(--branch-panel-height, 230px)) 14px auto 0 minmax(220px, 1fr);
}
.left-sidebar.branch-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 170px)) 14px minmax(220px, 1fr);
}
.left-sidebar.explorer-collapsed {
grid-template-rows: minmax(180px, var(--branch-panel-height, 230px)) 14px minmax(150px, var(--stash-panel-height, 170px)) 0 auto;
}
.left-sidebar.branch-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 minmax(220px, 1fr);
}
.left-sidebar.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: minmax(180px, var(--branch-panel-height, 230px)) 14px auto 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 170px)) 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 auto;
align-content: start;
}
.section-head { min-height: 40px; padding: 6px 10px; }
.repo-summary { height: 40px; padding: 0 10px; }
.repo-branch { max-width: 160px; }
@@ -7562,32 +7517,6 @@ input:focus, textarea:focus, select:focus { box-shadow: 0 0 0 3px color-mix(in s
.file-history-dialog-row time { display: none; }
.file-history-dialog-actions { display: grid; }
.file-history-dialog-actions button { width: 32px; min-width: 32px; padding: 0; overflow: hidden; color: var(--color-ink-muted); font-size: 0; gap: 0; }
.left-sidebar {
grid-template-rows: minmax(180px, var(--branch-panel-height, 240px)) 14px minmax(150px, var(--stash-panel-height, 180px)) 14px minmax(220px, 1fr);
min-height: 560px;
}
.left-sidebar:has(.stash-panel.collapsed) {
grid-template-rows: minmax(180px, var(--branch-panel-height, 240px)) 14px auto 0 minmax(220px, 1fr);
}
.left-sidebar.branch-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 180px)) 14px minmax(220px, 1fr);
}
.left-sidebar.explorer-collapsed {
grid-template-rows: minmax(120px, var(--branch-panel-height, 240px)) 14px minmax(150px, var(--stash-panel-height, 180px)) 0 auto;
}
.left-sidebar.branch-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 minmax(0, 1fr);
}
.left-sidebar.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: minmax(120px, var(--branch-panel-height, 240px)) 14px auto 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed {
grid-template-rows: auto 0 minmax(150px, var(--stash-panel-height, 180px)) 0 auto;
}
.left-sidebar.branch-collapsed.explorer-collapsed:has(.stash-panel.collapsed) {
grid-template-rows: auto 0 auto 0 auto;
align-content: start;
}
.top-section { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) 14px var(--commit-panel-height, 190px); }
.repo-form { grid-template-columns: 1fr; }
.repo-tabbar { grid-template-columns: auto minmax(0, 1fr) auto; }
@@ -9172,6 +9101,10 @@ section > header.page-header.page-header {
/* Compact accordion navigation (layout A). */
.left-sidebar { overflow-y: auto; overflow-x: hidden; }
/* While a border is being dragged, keep the cursor and stop text selection. */
.left-sidebar.resizing-panels { cursor: row-resize; user-select: none; }
.left-sidebar.resizing-panels * { pointer-events: none; }
.left-sidebar.resizing-panels .panel-resize-handle { pointer-events: auto; }
.left-sidebar > .panel { min-width: 0; }
.left-sidebar .section-head {
display: flex; align-items: center; justify-content: space-between; gap: 6px;
@@ -9193,7 +9126,7 @@ section > header.page-header.page-header {
.left-sidebar :is(.branch-create-toggle, .stash-toggle, .explorer-bulk-button):hover:not(:disabled) {
background: var(--color-surface-hover); color: var(--color-ink);
}
.left-sidebar .left-panel-resize-handle { min-height: 6px; }
.left-sidebar .left-panel-resize-handle { min-height: 8px; }
.left-sidebar .branch-list, .left-sidebar .explorer-list { padding: 4px 0; }
.left-sidebar .branch-group-toggle {
min-height: 30px; padding: 5px 10px; border-radius: 0;
@@ -9215,8 +9148,6 @@ section > header.page-header.page-header {
.left-sidebar .stash-input { grid-column: 1 / -1; }
.left-sidebar .explorer-tool-action, .left-sidebar .explorer-action-divider { display: none; }
/* File actions remain available through the file context menu. */
.left-sidebar .worktree-panel { display: grid; grid-template-rows: 42px minmax(0, 1fr); min-height: 0; overflow: hidden; }
.left-sidebar .worktree-panel.collapsed { grid-template-rows: 42px; }
.sidebar-worktree-list { min-height: 0; overflow: auto; padding: 4px 0; }
.sidebar-worktree-row {
display: flex; align-items: center; gap: 8px; width: 100%; min-height: 46px;
@@ -9244,8 +9175,6 @@ section > header.page-header.page-header {
.left-sidebar .section-head button svg { width: 14px; height: 14px; stroke-width: 1.75; }
.left-sidebar .section-head .pill-count { min-width: 24px; justify-content: center; }
.left-sidebar .tags-panel { display: grid; grid-template-rows: 42px minmax(0, 1fr); min-height: 0; overflow: hidden; }
.left-sidebar .tags-panel.collapsed { grid-template-rows: 42px; }
.sidebar-tags-list { min-height: 0; overflow: auto; padding: 4px 0; }
.left-sidebar .tags-panel .tag-create-form { grid-template-columns: auto minmax(0, 1fr) auto auto; margin: 4px 8px; }
.left-sidebar .tags-panel .tag-create-form input[aria-label="Tag message"] { grid-column: 2 / -1; grid-row: 2; }