@@ -313,13 +313,19 @@ struct MainLayout: View {
313313 . frame ( maxWidth: . infinity, maxHeight: . infinity)
314314
315315 // Bottom Panel (Terminal/Logs) - Resizable
316- if bottomPanelManager. isPanelVisible {
317- UnifiedBottomPanel ( panelManager: bottomPanelManager)
318- . frame ( height: bottomPanelManager. panelHeight)
319- . transition ( . move( edge: . bottom) )
320- // Force recreation of the panel when repository changes to ensure
321- // correct context (Terminal sessions, Integration tabs, etc.)
322- . id ( appState. currentRepository? . id. uuidString ?? " no-repo " )
316+ // Always show UnifiedBottomPanel - it handles both collapsed (28px tab bar) and expanded states
317+ // When fully hidden (no tabs), show minimal CollapsedBottomPanelBar
318+ if bottomPanelManager. openTabs. isEmpty && !bottomPanelManager. isPanelVisible {
319+ // No tabs open and panel hidden - show minimal bar to open terminal
320+ CollapsedBottomPanelBar ( panelManager: bottomPanelManager)
321+ } else {
322+ // Has tabs or panel is visible - show full UnifiedBottomPanel
323+ // UnifiedBottomPanel handles its own height (28px collapsed, panelHeight expanded)
324+ UnifiedBottomPanel ( panelManager: bottomPanelManager)
325+ . transition ( . move( edge: . bottom) )
326+ // Force recreation of the panel when repository changes to ensure
327+ // correct context (Terminal sessions, Integration tabs, etc.)
328+ . id ( appState. currentRepository? . id. uuidString ?? " no-repo " )
323329 }
324330 }
325331 . contextMenu { toolbarConfigurationMenu }
@@ -542,3 +548,69 @@ struct MainLayout: View {
542548 }
543549 }
544550}
551+
552+ // MARK: - Collapsed Bottom Panel Bar
553+ /// Minimal bar shown when bottom panel is hidden - click to expand
554+ struct CollapsedBottomPanelBar : View {
555+ @ObservedObject var panelManager : BottomPanelManager
556+ @State private var isHovered = false
557+
558+ var body : some View {
559+ HStack ( spacing: 6 ) {
560+ // Drag handle indicator
561+ Image ( systemName: " chevron.up " )
562+ . font ( . system( size: 8 , weight: . bold) )
563+ . foregroundColor ( AppTheme . textMuted)
564+
565+ // Show open tabs icons
566+ if !panelManager. openTabs. isEmpty {
567+ ForEach ( panelManager. openTabs. prefix ( 4 ) ) { tab in
568+ Image ( systemName: tab. type. icon)
569+ . font ( . system( size: 9 ) )
570+ . foregroundColor ( panelManager. activeTabId == tab. id ? AppTheme . accent : AppTheme . textMuted)
571+ }
572+ if panelManager. openTabs. count > 4 {
573+ Text ( " + \( panelManager. openTabs. count - 4 ) " )
574+ . font ( . system( size: 9 ) )
575+ . foregroundColor ( AppTheme . textMuted)
576+ }
577+ } else {
578+ Text ( " Terminal " )
579+ . font ( . system( size: 10 ) )
580+ . foregroundColor ( AppTheme . textMuted)
581+ }
582+
583+ Spacer ( )
584+
585+ // Quick action buttons
586+ Button {
587+ panelManager. openTab ( type: . terminal)
588+ } label: {
589+ Image ( systemName: " terminal " )
590+ . font ( . system( size: 9 ) )
591+ . foregroundColor ( AppTheme . textMuted)
592+ }
593+ . buttonStyle ( . plain)
594+ }
595+ . padding ( . horizontal, 12 )
596+ . frame ( height: 22 )
597+ . background ( isHovered ? AppTheme . hover : AppTheme . backgroundSecondary)
598+ . overlay (
599+ Rectangle ( )
600+ . fill ( AppTheme . border)
601+ . frame ( height: 1 ) ,
602+ alignment: . top
603+ )
604+ . contentShape ( Rectangle ( ) )
605+ . onTapGesture {
606+ withAnimation ( . spring( response: 0.3 ) ) {
607+ if panelManager. openTabs. isEmpty {
608+ panelManager. openTab ( type: . terminal)
609+ } else {
610+ panelManager. isPanelVisible = true
611+ }
612+ }
613+ }
614+ . onHover { isHovered = $0 }
615+ }
616+ }
0 commit comments