detached 5ed6481

feat(ui): hide active pane border when only one pane exists

commit
5ed64810f0f52ac5d2c40f85aa2dad6c83e4d634
author
brice · · 2025-12-23 06:19 UTC
parent
b2baf19
signature
unsigned
2 files · +27 -0
M internal/ui/component/workspace_view.go +22 -0
@@ -172,6 +172,9 @@ func (wv *WorkspaceView) SetWorkspace(ctx context.Context, ws *entity.Workspace)
172172 }
173173 }
174174
175+ // Update single-pane mode based on pane count
176+ wv.updateSinglePaneModeInternal()
177+
175178 return nil
176179 }
177180
@@ -275,6 +278,23 @@ func (wv *WorkspaceView) PaneCount() int {
275278 return len(wv.paneViews)
276279 }
277280
281+// singlePaneClass is used to hide the active pane border when only one pane exists.
282+const singlePaneClass = "single-pane"
283+
284+// updateSinglePaneModeInternal adds/removes the single-pane CSS class on the container.
285+// Must be called with the lock held.
286+func (wv *WorkspaceView) updateSinglePaneModeInternal() {
287+ if wv.container == nil {
288+ return
289+ }
290+
291+ if len(wv.paneViews) <= 1 {
292+ wv.container.AddCssClass(singlePaneClass)
293+ } else {
294+ wv.container.RemoveCssClass(singlePaneClass)
295+ }
296+}
297+
278298 // SetOnPaneFocused sets the callback for when a pane receives focus.
279299 func (wv *WorkspaceView) SetOnPaneFocused(fn func(paneID entity.PaneID)) {
280300 wv.mu.Lock()
@@ -356,6 +376,7 @@ func (wv *WorkspaceView) RegisterPaneView(paneID entity.PaneID, pv *PaneView) {
356376 defer wv.mu.Unlock()
357377
358378 wv.paneViews[paneID] = pv
379+ wv.updateSinglePaneModeInternal()
359380 }
360381
361382 // UnregisterPaneView removes a PaneView from the tracking map.
@@ -365,6 +386,7 @@ func (wv *WorkspaceView) UnregisterPaneView(paneID entity.PaneID) {
365386 defer wv.mu.Unlock()
366387
367388 delete(wv.paneViews, paneID)
389+ wv.updateSinglePaneModeInternal()
368390 }
369391
370392 // GetRootWidget returns the current root widget of the workspace.
@@ -172,6 +172,9 @@ func (wv *WorkspaceView) SetWorkspace(ctx context.Context, ws *entity.Workspace)
172 }172 }
173 }173 }
174 174
175+ // Update single-pane mode based on pane count
176+ wv.updateSinglePaneModeInternal()
177+
175 return nil178 return nil
176 }179 }
177 180
@@ -275,6 +278,23 @@ func (wv *WorkspaceView) PaneCount() int {
275 return len(wv.paneViews)278 return len(wv.paneViews)
276 }279 }
277 280
281+// singlePaneClass is used to hide the active pane border when only one pane exists.
282+const singlePaneClass = "single-pane"
283+
284+// updateSinglePaneModeInternal adds/removes the single-pane CSS class on the container.
285+// Must be called with the lock held.
286+func (wv *WorkspaceView) updateSinglePaneModeInternal() {
287+ if wv.container == nil {
288+ return
289+ }
290+
291+ if len(wv.paneViews) <= 1 {
292+ wv.container.AddCssClass(singlePaneClass)
293+ } else {
294+ wv.container.RemoveCssClass(singlePaneClass)
295+ }
296+}
297+
278 // SetOnPaneFocused sets the callback for when a pane receives focus.298 // SetOnPaneFocused sets the callback for when a pane receives focus.
279 func (wv *WorkspaceView) SetOnPaneFocused(fn func(paneID entity.PaneID)) {299 func (wv *WorkspaceView) SetOnPaneFocused(fn func(paneID entity.PaneID)) {
280 wv.mu.Lock()300 wv.mu.Lock()
@@ -356,6 +376,7 @@ func (wv *WorkspaceView) RegisterPaneView(paneID entity.PaneID, pv *PaneView) {
356 defer wv.mu.Unlock()376 defer wv.mu.Unlock()
357 377
358 wv.paneViews[paneID] = pv378 wv.paneViews[paneID] = pv
379+ wv.updateSinglePaneModeInternal()
359 }380 }
360 381
361 // UnregisterPaneView removes a PaneView from the tracking map.382 // UnregisterPaneView removes a PaneView from the tracking map.
@@ -365,6 +386,7 @@ func (wv *WorkspaceView) UnregisterPaneView(paneID entity.PaneID) {
365 defer wv.mu.Unlock()386 defer wv.mu.Unlock()
366 387
367 delete(wv.paneViews, paneID)388 delete(wv.paneViews, paneID)
389+ wv.updateSinglePaneModeInternal()
368 }390 }
369 391
370 // GetRootWidget returns the current root widget of the workspace.392 // GetRootWidget returns the current root widget of the workspace.
M internal/ui/theme/css.go +5 -0
@@ -396,6 +396,11 @@ func generatePaneCSS(p Palette) string {
396396 border: 0.0625em solid var(--accent);
397397 }
398398
399+/* Hide active border when only one pane exists */
400+.single-pane .pane-active {
401+ border-color: transparent;
402+}
403+
399404 /* Pane mode active - thick blue inset border (for overlay) */
400405 .pane-mode-active {
401406 background-color: transparent;
@@ -396,6 +396,11 @@ func generatePaneCSS(p Palette) string {
396 border: 0.0625em solid var(--accent);396 border: 0.0625em solid var(--accent);
397 }397 }
398 398
399+/* Hide active border when only one pane exists */
400+.single-pane .pane-active {
401+ border-color: transparent;
402+}
403+
399 /* Pane mode active - thick blue inset border (for overlay) */404 /* Pane mode active - thick blue inset border (for overlay) */
400 .pane-mode-active {405 .pane-mode-active {
401 background-color: transparent;406 background-color: transparent;

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close