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) | |||
| 172 | 172 | } | |
| 173 | 173 | } | |
| 174 | 174 | ||
| 175 | + | // Update single-pane mode based on pane count | |
| 176 | + | wv.updateSinglePaneModeInternal() | |
| 177 | + | ||
| 175 | 178 | return nil | |
| 176 | 179 | } | |
| 177 | 180 | ||
| @@ -275,6 +278,23 @@ func (wv *WorkspaceView) PaneCount() int { | |||
| 275 | 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 | 298 | // SetOnPaneFocused sets the callback for when a pane receives focus. | |
| 279 | 299 | func (wv *WorkspaceView) SetOnPaneFocused(fn func(paneID entity.PaneID)) { | |
| 280 | 300 | wv.mu.Lock() | |
| @@ -356,6 +376,7 @@ func (wv *WorkspaceView) RegisterPaneView(paneID entity.PaneID, pv *PaneView) { | |||
| 356 | 376 | defer wv.mu.Unlock() | |
| 357 | 377 | ||
| 358 | 378 | wv.paneViews[paneID] = pv | |
| 379 | + | wv.updateSinglePaneModeInternal() | |
| 359 | 380 | } | |
| 360 | 381 | ||
| 361 | 382 | // UnregisterPaneView removes a PaneView from the tracking map. | |
| @@ -365,6 +386,7 @@ func (wv *WorkspaceView) UnregisterPaneView(paneID entity.PaneID) { | |||
| 365 | 386 | defer wv.mu.Unlock() | |
| 366 | 387 | ||
| 367 | 388 | delete(wv.paneViews, paneID) | |
| 389 | + | wv.updateSinglePaneModeInternal() | |
| 368 | 390 | } | |
| 369 | 391 | ||
| 370 | 392 | // 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 nil | 178 | 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] = pv | 378 | 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 { | |||
| 396 | 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 | 404 | /* Pane mode active - thick blue inset border (for overlay) */ | |
| 400 | 405 | .pane-mode-active { | |
| 401 | 406 | 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; | ||