Some checks are pending
CI / test (push) Waiting to run
Tighten the inbox, detail, and watch layouts so approval actions feel denser and more direct across compact surfaces.
108 lines
3.3 KiB
Swift
108 lines
3.3 KiB
Swift
import SwiftUI
|
|
|
|
struct PrimaryActionStyle: ButtonStyle {
|
|
func makeBody(configuration: Configuration) -> some View {
|
|
configuration.label
|
|
.font(.footnote.weight(.semibold))
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.horizontal, 12)
|
|
.padding(.vertical, 10)
|
|
.foregroundStyle(Color.idpPrimaryForeground)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: IdP.controlRadius, style: .continuous)
|
|
.fill(Color.idpPrimary)
|
|
)
|
|
.opacity(configuration.isPressed ? 0.85 : 1)
|
|
}
|
|
}
|
|
|
|
struct SecondaryActionStyle: ButtonStyle {
|
|
func makeBody(configuration: Configuration) -> some View {
|
|
configuration.label
|
|
.font(.footnote.weight(.semibold))
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.horizontal, 12)
|
|
.padding(.vertical, 10)
|
|
.foregroundStyle(.white)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: IdP.controlRadius, style: .continuous)
|
|
.fill(Color.clear)
|
|
)
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: IdP.controlRadius, style: .continuous)
|
|
.stroke(Color.white.opacity(0.22), lineWidth: 1)
|
|
)
|
|
.opacity(configuration.isPressed ? 0.7 : 1)
|
|
}
|
|
}
|
|
|
|
struct DestructiveStyle: ButtonStyle {
|
|
func makeBody(configuration: Configuration) -> some View {
|
|
configuration.label
|
|
.font(.footnote.weight(.semibold))
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.horizontal, 12)
|
|
.padding(.vertical, 10)
|
|
.foregroundStyle(.white)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: IdP.controlRadius, style: .continuous)
|
|
.fill(Color.idpDestructive)
|
|
)
|
|
.opacity(configuration.isPressed ? 0.85 : 1)
|
|
}
|
|
}
|
|
|
|
struct WatchBadge: View {
|
|
enum Tone {
|
|
case neutral
|
|
case accent
|
|
case ok
|
|
case warn
|
|
case danger
|
|
}
|
|
|
|
let title: String
|
|
var tone: Tone = .neutral
|
|
|
|
var body: some View {
|
|
Text(title)
|
|
.font(.system(size: 9, weight: .bold))
|
|
.tracking(0.5)
|
|
.foregroundStyle(foreground)
|
|
.padding(.horizontal, 6)
|
|
.padding(.vertical, 2)
|
|
.background(background, in: Capsule(style: .continuous))
|
|
.overlay(
|
|
Capsule(style: .continuous)
|
|
.stroke(stroke, lineWidth: 1)
|
|
)
|
|
}
|
|
|
|
private var foreground: Color {
|
|
switch tone {
|
|
case .neutral: return Color.idpMutedForeground
|
|
case .accent: return IdP.tint
|
|
case .ok: return Color.idpOK
|
|
case .warn: return Color.idpWarn
|
|
case .danger: return Color.idpDestructive
|
|
}
|
|
}
|
|
|
|
private var background: Color {
|
|
switch tone {
|
|
case .neutral: return Color.white.opacity(0.05)
|
|
default: return .clear
|
|
}
|
|
}
|
|
|
|
private var stroke: Color {
|
|
switch tone {
|
|
case .accent: return IdP.tint.opacity(0.45)
|
|
case .ok: return Color.idpOK.opacity(0.45)
|
|
case .warn: return Color.idpWarn.opacity(0.45)
|
|
case .danger: return Color.idpDestructive.opacity(0.55)
|
|
case .neutral: return .clear
|
|
}
|
|
}
|
|
}
|