diff --git a/Paxo/UI/PaxoStyle.swift b/Paxo/UI/PaxoStyle.swift index 69f6e99..e48d479 100644 --- a/Paxo/UI/PaxoStyle.swift +++ b/Paxo/UI/PaxoStyle.swift @@ -1,25 +1,33 @@ import AppKit import SwiftUI -/// 모든 앱 화면에서 같은 브랜드 색상과 불투명 배경을 사용한다. +/// 모든 앱 화면에서 같은 브랜드 색상과 표면 스타일을 사용한다. enum PaxoStyle { static let brand = Color(red: 27 / 255, green: 118 / 255, blue: 1) static let cornerRadius: CGFloat = 14 } extension View { - func paxoSurface(cornerRadius: CGFloat = PaxoStyle.cornerRadius) -> some View { - background(Color(nsColor: .windowBackgroundColor)) - .overlay { - RoundedRectangle(cornerRadius: cornerRadius) - .strokeBorder(.primary.opacity(0.1), lineWidth: 0.5) + func paxoSurface( + cornerRadius: CGFloat = PaxoStyle.cornerRadius, isOpaque: Bool = false + ) -> some View { + background { + if isOpaque { + Color(nsColor: .windowBackgroundColor) + } else { + PaxoGlassBackground() } - .clipShape(RoundedRectangle(cornerRadius: cornerRadius)) - .tint(PaxoStyle.brand) + } + .overlay { + RoundedRectangle(cornerRadius: cornerRadius) + .strokeBorder(.primary.opacity(0.1), lineWidth: 0.5) + } + .clipShape(RoundedRectangle(cornerRadius: cornerRadius)) + .tint(PaxoStyle.brand) } func paxoWindowSurface() -> some View { - paxoSurface(cornerRadius: 0) + paxoSurface(cornerRadius: 0, isOpaque: true) .background(PaxoWindowBackground()) .toolbarBackground(.hidden, for: .windowToolbar) } @@ -49,3 +57,37 @@ private final class WindowBackgroundView: NSView { window.titlebarAppearsTransparent = true } } + +private struct PaxoGlassBackground: View { + @Environment(\.accessibilityReduceTransparency) private var reduceTransparency + + var body: some View { + Group { + if reduceTransparency { + Color(nsColor: .windowBackgroundColor) + } else { + WindowGlass() + } + } + .allowsHitTesting(false) + .accessibilityHidden(true) + } +} + +/// 창 뒤의 배경을 흐리게 하면서 텍스트 대비를 유지한다. +private struct WindowGlass: NSViewRepresentable { + @Environment(\.colorScheme) private var colorScheme + + func makeNSView(context: Context) -> NSVisualEffectView { + let view = NSVisualEffectView() + view.blendingMode = .behindWindow + view.material = .hudWindow + view.state = .active + updateNSView(view, context: context) + return view + } + + func updateNSView(_ view: NSVisualEffectView, context: Context) { + view.appearance = NSAppearance(named: colorScheme == .dark ? .darkAqua : .aqua) + } +}