import SwiftUI struct ApprovalCardModifier: ViewModifier { var highlighted = false func body(content: Content) -> some View { content .padding(8) .background( RoundedRectangle(cornerRadius: IdP.cardRadius, style: .continuous) .fill(Color.clear) ) .overlay( RoundedRectangle(cornerRadius: IdP.cardRadius, style: .continuous) .stroke(highlighted ? IdP.tint.opacity(0.55) : Color.white.opacity(0.12), lineWidth: 1) ) } } extension View { func approvalCard(highlighted: Bool = false) -> some View { modifier(ApprovalCardModifier(highlighted: highlighted)) } } struct RequestHeroCard: View { let request: ApprovalRequest let handle: String var body: some View { VStack(alignment: .leading, spacing: 6) { HStack(spacing: 5) { MonogramAvatar(title: request.source, size: 18) Text(request.source) .font(.system(size: 11, weight: .medium)) .foregroundStyle(Color.idpMutedForeground) .lineLimit(1) } HStack(spacing: 4) { Text("Sign in as") .foregroundStyle(.white) Text(handle) .foregroundStyle(IdP.tint) .fontWeight(.semibold) Text("?") .foregroundStyle(.white) } .font(.system(size: 15, weight: .semibold)) .lineLimit(2) } .frame(maxWidth: .infinity, alignment: .leading) } } struct MonogramAvatar: View { let title: String var size: CGFloat = 20 var tint: Color = IdP.tint private var monogram: String { let letters = title .replacingOccurrences(of: "auth.", with: "") .split { !$0.isLetter && !$0.isNumber } .prefix(2) .compactMap { $0.first } let glyph = String(letters.map(Character.init)) return glyph.isEmpty ? "I" : glyph.uppercased() } var body: some View { ZStack { RoundedRectangle(cornerRadius: 5, style: .continuous) .fill(tint) Text(monogram) .font(.system(size: size * (monogram.count > 1 ? 0.36 : 0.44), weight: .bold)) .foregroundStyle(.white) .tracking(-0.3) } .frame(width: size, height: size) .accessibilityHidden(true) } } enum BrandTint { static func color(for host: String) -> Color { let key = host.lowercased() if key.contains("github") { return Color(red: 0.14, green: 0.16, blue: 0.18) } if key.contains("lufthansa") { return Color(red: 0.02, green: 0.09, blue: 0.30) } if key.contains("hetzner") { return Color(red: 0.84, green: 0.05, blue: 0.18) } if key.contains("notion") { return Color(red: 0.12, green: 0.12, blue: 0.12) } if key.contains("apple") { return Color(red: 0.18, green: 0.18, blue: 0.22) } if key.contains("reddit") { return Color(red: 1.00, green: 0.27, blue: 0.00) } if key.contains("cli") { return Color(red: 0.24, green: 0.26, blue: 0.32) } if key.contains("workspace") { return Color(red: 0.26, green: 0.38, blue: 0.88) } if key.contains("foss") || key.contains("berlin-mbp") { return Color(red: 0.12, green: 0.45, blue: 0.70) } return IdP.tint } }