mana-swift-ui/Sources/ManaFeedbackUI/ManaFeedbackCard.swift
Till JS 93355c1e10 Karten-Chrome vereinheitlichen: .manaCard + RoundedRectangle.mana + ManaAboutSection
- ManaThemeUI: geteiltes Karten-Chrome `.manaCard(...)` (continuous Squircle +
  optionaler Border aus EINER gemeinsamen Form, saubere Ecken) und
  `RoundedRectangle.mana(Radius.*)` als geteilte Ecken-Sprache.
- ManaSignInCTA (Login) + ManaFeedbackCard ziehen auf `.manaCard` — identisches
  Chrome, Login bekommt denselben Border, beide continuous.
- Rest-Chrome (Eingabefelder, Primary-Button, Feedback-Buttons, 2FA-QR/Codes/
  Kopier-Buttons) auf `RoundedRectangle.mana(Radius.*)`; keine cornerRadius-
  Literale mehr, Radien auf Token-Skala konvergiert.
- ManaAboutSection: vereinheitlichte „Über"-Sektion (App/Version/Build + Links),
  opt-in via `ManaAccountView(about:)`.

Kein API-Bruch (alles additiv/optisch). CHANGELOG aktualisiert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 13:26:26 +02:00

90 lines
3.5 KiB
Swift

import ManaCore
import ManaThemeUI
import ManaTokens
import SwiftUI
/// Prominenter Feedback-Block für den Konto-/Einstellungen-Tab — der
/// gewichtige Bruder der dezenten ``ManaFeedbackButton``-Listenzeile.
/// Icon + aktivierender Titel + ein Satz Einladung + gefüllter CTA in
/// Vereinsfarbe. Präsentiert dasselbe ``ManaFeedbackSheet``.
///
/// Wird typischerweise nicht von Hand platziert, sondern von
/// `ManaAccountView` an **fester Position** gerendert (direkt nach dem
/// Konto-/Anmelden-Block) — so steht Feedback in allen Verein-Apps gleich
/// weit oben und gleich auffällig, statt pro App handgebaut tief im
/// `extra`-Slot zu verschwinden.
///
/// Für Stand-alone-Einsatz (eigener Settings-Screen) in eine `Section`
/// mit geleertem Row-Background + Null-Insets legen, damit die Karte frei
/// in der `Form` schwebt:
///
/// ```swift
/// Section {
/// ManaFeedbackCard(client: client, isLoggedIn: session.isLoggedIn)
/// .listRowInsets(EdgeInsets())
/// .listRowBackground(Color.clear)
/// }
/// ```
public struct ManaFeedbackCard: View {
@Environment(\.manaTheme) private var theme
private let client: FeedbackClient
private let isLoggedIn: Bool
private let title: String
private let message: String
private let cta: String
@State private var isPresented = false
/// - Parameters:
/// - client: der App-`FeedbackClient` (trägt die `appId`).
/// - isLoggedIn: steuert das anonyme Kontakt-Mail-Feld im Sheet.
/// - title: aktivierende Überschrift. Default: Mitgestalten-Ton.
/// - message: ein Satz Einladung darunter.
/// - cta: Beschriftung des gefüllten Knopfs.
public init(
client: FeedbackClient,
isLoggedIn: Bool,
title: String = "Hilf mit, die App zu formen",
message: String = "Deine Wünsche steuern, was wir als Nächstes bauen — ein Mensch im Team liest mit.",
cta: String = "Vorschlag senden"
) {
self.client = client
self.isLoggedIn = isLoggedIn
self.title = title
self.message = message
self.cta = cta
}
public var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack(spacing: 10) {
Image(systemName: "bubble.left.and.bubble.right.fill")
.font(.title3)
.foregroundStyle(theme.primary)
Text(title)
.font(.headline)
.foregroundStyle(theme.foreground)
}
Text(message)
.font(.subheadline)
.foregroundStyle(theme.mutedForeground)
.fixedSize(horizontal: false, vertical: true)
Button { isPresented = true } label: {
Text(cta)
.fontWeight(.semibold)
.frame(maxWidth: .infinity)
.padding(.vertical, 12)
.background(theme.primary, in: RoundedRectangle.mana(Radius.md))
.foregroundStyle(theme.primaryForeground)
}
.buttonStyle(.plain)
}
// Geteiltes Karten-Chrome: continuous Squircle-Ecken + Border aus einer
// gemeinsamen Form (vorher zwei getrennte circular RoundedRectangles,
// deren Border den Ecken nicht sauber folgte). Radius jetzt einheitlich
// mit dem Login-CTA (Radius.lg) statt eigener 16.
.manaCard(surface: theme.surface, border: theme.border)
.manaFeedbackSheet(isPresented: $isPresented, client: client, isLoggedIn: isLoggedIn)
}
}