Centralize shared card surface styling
This commit is contained in:
parent
8a1677565d
commit
c7659ccda3
@ -1,6 +1,65 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import SwiftUI
|
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 {
|
struct ToolbarShareButton: View {
|
||||||
let systemImage: String
|
let systemImage: String
|
||||||
let isEnabled: Bool
|
let isEnabled: Bool
|
||||||
|
|||||||
@ -253,7 +253,7 @@ private struct SourceDetailView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(18)
|
.padding(18)
|
||||||
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous))
|
.appCardSurface(.primaryPanel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ private struct SourceDetailView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(18)
|
.padding(18)
|
||||||
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 18, style: .continuous))
|
.appCardSurface(.primaryPanel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1083,7 +1083,7 @@ struct ItemDetailView: View {
|
|||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.padding(18)
|
.padding(18)
|
||||||
.background(.quaternary.opacity(0.32), in: RoundedRectangle(cornerRadius: 18, style: .continuous))
|
.appCardSurface(.secondaryPanel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -180,7 +180,7 @@ private struct SourceHeaderRow: View {
|
|||||||
}
|
}
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(backgroundStyle, in: RoundedRectangle(cornerRadius: 10, style: .continuous))
|
.appSidebarRowSurface(isHighlighted: isHovering && !isSelected)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture(perform: onSelect)
|
.onTapGesture(perform: onSelect)
|
||||||
.onHover { isHovering = $0 }
|
.onHover { isHovering = $0 }
|
||||||
@ -229,15 +229,6 @@ private struct SourceHeaderRow: View {
|
|||||||
private var availabilityBadgeEmphasis: Bool {
|
private var availabilityBadgeEmphasis: Bool {
|
||||||
source.availability == .limited
|
source.availability == .limited
|
||||||
}
|
}
|
||||||
|
|
||||||
private var backgroundStyle: AnyShapeStyle {
|
|
||||||
if isHovering && !isSelected {
|
|
||||||
return AnyShapeStyle(.secondary.opacity(0.08))
|
|
||||||
}
|
|
||||||
|
|
||||||
return AnyShapeStyle(.clear)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var statusIndicator: some View {
|
private var statusIndicator: some View {
|
||||||
if source.isScanning {
|
if source.isScanning {
|
||||||
|
|||||||
@ -284,7 +284,7 @@ struct ConnectedDeviceSourcePickerView: View {
|
|||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
|
.appCardSurface(.placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func emptyState(_ title: String) -> some View {
|
private func emptyState(_ title: String) -> some View {
|
||||||
@ -298,6 +298,6 @@ struct ConnectedDeviceSourcePickerView: View {
|
|||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 16, style: .continuous))
|
.appCardSurface(.placeholder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user