Centralize shared card surface styling

This commit is contained in:
John Burwell 2026-05-28 20:49:23 -05:00
parent 8a1677565d
commit c7659ccda3
4 changed files with 65 additions and 15 deletions

View File

@ -1,6 +1,65 @@
import AppKit
import SwiftUI
enum AppChrome {
static let sidebarRowCornerRadius: CGFloat = 10
static let placeholderCardCornerRadius: CGFloat = 16
static let panelCardCornerRadius: CGFloat = 18
}
enum AppCardStyle {
case primaryPanel
case secondaryPanel
case placeholder
fileprivate var cornerRadius: CGFloat {
switch self {
case .primaryPanel, .secondaryPanel:
return AppChrome.panelCardCornerRadius
case .placeholder:
return AppChrome.placeholderCardCornerRadius
}
}
fileprivate var fillStyle: AnyShapeStyle {
switch self {
case .primaryPanel:
return AnyShapeStyle(.regularMaterial)
case .secondaryPanel:
return AnyShapeStyle(.quaternary.opacity(0.32))
case .placeholder:
return AnyShapeStyle(.thinMaterial)
}
}
}
private struct AppCardSurfaceModifier: ViewModifier {
let style: AppCardStyle
func body(content: Content) -> some View {
content.background(
style.fillStyle,
in: RoundedRectangle(cornerRadius: style.cornerRadius, style: .continuous)
)
}
}
extension View {
func appCardSurface(_ style: AppCardStyle) -> some View {
modifier(AppCardSurfaceModifier(style: style))
}
func appSidebarRowSurface(isHighlighted: Bool) -> some View {
let fillStyle = isHighlighted
? AnyShapeStyle(.secondary.opacity(0.08))
: AnyShapeStyle(Color.clear)
return background(
fillStyle,
in: RoundedRectangle(cornerRadius: AppChrome.sidebarRowCornerRadius, style: .continuous)
)
}
}
struct ToolbarShareButton: View {
let systemImage: String
let isEnabled: Bool

View File

@ -253,7 +253,7 @@ private struct SourceDetailView: View {
}
}
.padding(18)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous))
.appCardSurface(.primaryPanel)
}
}
@ -609,7 +609,7 @@ private struct SourceDetailView: View {
}
}
.padding(18)
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous))
.appCardSurface(.primaryPanel)
}
}
}
@ -1083,7 +1083,7 @@ struct ItemDetailView: View {
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(18)
.background(.quaternary.opacity(0.32), in: RoundedRectangle(cornerRadius: 18, style: .continuous))
.appCardSurface(.secondaryPanel)
}
}

View File

@ -180,7 +180,7 @@ private struct SourceHeaderRow: View {
}
.padding(.horizontal, 10)
.padding(.vertical, 8)
.background(backgroundStyle, in: RoundedRectangle(cornerRadius: 10, style: .continuous))
.appSidebarRowSurface(isHighlighted: isHovering && !isSelected)
.contentShape(Rectangle())
.onTapGesture(perform: onSelect)
.onHover { isHovering = $0 }
@ -229,15 +229,6 @@ private struct SourceHeaderRow: View {
private var availabilityBadgeEmphasis: Bool {
source.availability == .limited
}
private var backgroundStyle: AnyShapeStyle {
if isHovering && !isSelected {
return AnyShapeStyle(.secondary.opacity(0.08))
}
return AnyShapeStyle(.clear)
}
@ViewBuilder
private var statusIndicator: some View {
if source.isScanning {

View File

@ -284,7 +284,7 @@ struct ConnectedDeviceSourcePickerView: View {
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
.appCardSurface(.placeholder)
}
private func emptyState(_ title: String) -> some View {
@ -298,6 +298,6 @@ struct ConnectedDeviceSourcePickerView: View {
.multilineTextAlignment(.center)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
.appCardSurface(.placeholder)
}
}