diff --git a/MacApp/.swiftlint.yml b/MacApp/.swiftlint.yml index 89ae0ae..0df5375 100644 --- a/MacApp/.swiftlint.yml +++ b/MacApp/.swiftlint.yml @@ -142,10 +142,10 @@ custom_rules: regex: '\bColor\.black\b' message: "Use DS.Color.* semantic tokens instead of Color.black." severity: error - # Wave 2 note: the `Relay` target remains excluded because AppRootView uses - # Color.black as the terminal canvas background fallback — the canvas is - # outside the design-system semantic palette and migrates in Wave 6 - # alongside the terminal-specific theming pipeline. + # Relay target stays excluded until two further `Color.black` fallbacks + # in AppRootView (lines for the Welcome-transition canvas and the + # NoSessionPlaceholder backdrop) are replaced with theme-aware tokens. + # Tracked as a follow-up cleanup to the Wave 6 rollout. excluded: - "Packages/RemoteTerminal" - "Packages/TerminalSwiftTerm" diff --git a/MacApp/Relay/AppRootView.swift b/MacApp/Relay/AppRootView.swift index 8467e9b..5c501ef 100644 --- a/MacApp/Relay/AppRootView.swift +++ b/MacApp/Relay/AppRootView.swift @@ -2,6 +2,7 @@ import AgentOrchestrator import ComposableArchitecture import DesignSystem import PaneManager +import SharedModels import SwiftUI import TerminalFeature import UniformTypeIdentifiers @@ -186,29 +187,36 @@ private struct AgentTerminalView: View { let registry: TerminalSessionRegistry @Environment(\.accessibilityReduceMotion) private var reduceMotion + @Environment(\.terminalTheme) private var terminalTheme var body: some View { VStack(spacing: 0) { - // Terminal view - if let sessionID = store.terminal.sessionID { - TerminalViewRepresentable( - sessionID: sessionID, - registry: registry, - configuration: store.terminal.configuration, - reduceMotion: reduceMotion - ) - .frame(maxWidth: .infinity, maxHeight: .infinity) - } else { - // Terminal canvas background — see note above on `Color.black`. - Color.black - .frame(maxWidth: .infinity, maxHeight: .infinity) + // Terminal canvas — framed inside rounded chrome so the content + // surface shows through around the edges. Connecting-state + // fallback mirrors the user's chosen terminal palette so there + // is no black flash before the palette is applied. + Group { + if let sessionID = store.terminal.sessionID { + TerminalViewRepresentable( + sessionID: sessionID, + registry: registry, + configuration: store.terminal.configuration, + reduceMotion: reduceMotion + ) + } else { + Color(nsColor: terminalTheme.background.nsColor) + } } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .clipShape(.rect(cornerRadius: DS.Radius.sm, style: .continuous)) + .padding(DS.Spacing.xs) - Divider() - - // Status bar + // Status bar — no divider: colour contrast between the content + // surface chrome and the canvas beneath the chrome carries the + // separation. AgentStatusBarView(store: store) } + .background(DS.Color.surfaceContent) } }