diff --git a/App/ResourcesPanel.swift b/App/ResourcesPanel.swift index 48d0af8..7172b7c 100644 --- a/App/ResourcesPanel.swift +++ b/App/ResourcesPanel.swift @@ -8,13 +8,22 @@ import ShepherdrCore struct ResourcesPanel: View { let workspace: SessionWorkspace let checks: ChecksMonitor + /// Hides the panel; the toolbar toggle is still there to bring it back. + let close: () -> Void private static let shown = 10 @ViewState private var expanded = Set() var body: some View { VStack(alignment: .leading, spacing: 0) { - ConsoleHeader(title: "Resources", trailing: "\(workspace.visibleResources.count)") - .padding(.horizontal, 12).padding(.top, 10).padding(.bottom, 6) + HStack(spacing: 8) { + ConsoleHeader(title: "Resources", trailing: "\(workspace.visibleResources.count)") + Button(action: close) { + Text("✕").font(Theme.mono(10.5, .semibold)).foregroundStyle(Theme.dim) + } + .buttonStyle(.plain) + .help("Close Resources panel — the ≡ button in the header brings it back") + } + .padding(.horizontal, 12).padding(.top, 10).padding(.bottom, 6) ScrollView { VStack(alignment: .leading, spacing: 0) { ForEach(SessionResource.Kind.allCases, id: \.self) { kind in diff --git a/App/SessionView.swift b/App/SessionView.swift index e57e8f9..7838fd8 100644 --- a/App/SessionView.swift +++ b/App/SessionView.swift @@ -37,7 +37,8 @@ struct SessionView: View { workArea if showsResources && !workspace.visibleResources.isEmpty { Rectangle().fill(Theme.line).frame(width: 1) - ResourcesPanel(workspace: workspace, checks: model.checksMonitor).frame(width: 230) + ResourcesPanel(workspace: workspace, checks: model.checksMonitor) { showsResources = false } + .frame(width: 230) } } } @@ -125,10 +126,14 @@ struct SessionView: View { Spacer(minLength: 8) if let agent = context.agent { StateTag(state: agent.agent.state, stale: agent.isStale) } lockButton - Button { terminal.open() } label: { Text("↻") } - .buttonStyle(ConsoleButtonStyle(tint: Theme.dim)) - .disabled(terminal.status == .connecting || !context.canConnect) - .help("Reconnect to this terminal") + HStack(spacing: 4) { + Button { terminal.open() } label: { Text("↻").frame(width: 16, height: 14) } + .buttonStyle(ConsoleButtonStyle(tint: Theme.dim)) + .disabled(terminal.status == .connecting || !context.canConnect) + .help("Reconnect to this terminal") + resourcesButton + browserButton + } Button { showDetails.toggle() } label: { Text("i") } .buttonStyle(ConsoleButtonStyle(tint: Theme.dim)) .help("Session details") @@ -163,6 +168,23 @@ struct SessionView: View { .accessibilityLabel(locked ? "Unlock session" : "Lock session") } + private var resourcesButton: some View { + let links = workspace.visibleResources.count + return Button { showsResources.toggle() } label: { Text("≡").frame(width: 16, height: 14) } + .buttonStyle(ConsoleButtonStyle(tint: showsResources && links > 0 ? Theme.phosphor : Theme.dim)) + .disabled(links == 0) + .help(links > 0 ? "Pull requests, issues and Claude artifacts this session linked to" + : "Pull requests, issues and Claude artifacts this session links to gather here") + } + + private var browserButton: some View { + Button { model.toggleBrowser() } label: { + Image(systemName: "globe").font(.system(size: 11, weight: .semibold)).frame(width: 16, height: 14) + } + .buttonStyle(ConsoleButtonStyle(tint: workspace.browser.isVisible ? Theme.phosphor : Theme.dim)) + .help("This session's browser (⌘B). Its tabs stay open while you work elsewhere.") + } + // MARK: Banners and states private func banner(_ message: String, dismiss: (() -> Void)? = nil, action: (String, () -> Void)? = nil) -> some View { @@ -278,25 +300,6 @@ struct SessionView: View { key("↓", .down, help: "Down arrow") key("⏎", .enter, help: "Return") Spacer(minLength: 8) - if !compact { - Text(isLive ? "⇧⏎ new line · click a link to browse · ⌘-click opens your browser" : "locked · read-only · ⌘E to unlock") - .font(Theme.mono(9.5)).foregroundStyle(Theme.faint).lineLimit(1).truncationMode(.head) - .layoutPriority(-1) - } - let links = workspace.visibleResources.count - barToggle(compact ? (links > 0 ? "≡ \(links)" : "≡") : (links > 0 ? "≡ RESOURCES \(links)" : "≡ RESOURCES"), - active: showsResources && links > 0, - help: links > 0 ? "Pull requests, issues and Claude artifacts this session linked to" - : "Pull requests, issues and Claude artifacts this session links to gather here") { - showsResources.toggle() - } - .disabled(links == 0) - let tabs = workspace.browser.tabs.count - barToggle(compact ? (tabs > 0 ? "◫ \(tabs)" : "◫") : (tabs > 0 ? "◫ BROWSER \(tabs)" : "◫ BROWSER"), - active: workspace.browser.isVisible, - help: "This session's browser (⌘B). Its tabs stay open while you work elsewhere.") { - model.toggleBrowser() - } } }