import SwiftUI #if canImport(UIKit) import UIKit #endif /// Vier Rating-Buttons mit emphasis auf "Good" (full-width primary). /// Web-Vorbild: `cards/apps/web/src/routes/study/[deckId]/+page.svelte` /// — `.grade.again/.hard/.good/.easy`-Klassen. struct RatingBar: View { let onRate: (Rating) -> Void var body: some View { HStack(spacing: 8) { ForEach(Rating.allCases, id: \.self) { rating in Button { triggerHaptic(for: rating) onRate(rating) } label: { HStack(spacing: 6) { Text(rating.label) .font(.subheadline.weight(.semibold)) Text(rating.shortcut) .font(.caption2.weight(.semibold)) .padding(.horizontal, 5) .padding(.vertical, 1) .background(kbdBackground(for: rating), in: RoundedRectangle(cornerRadius: 4)) .foregroundStyle(kbdForeground(for: rating)) } .frame(maxWidth: .infinity) .padding(.vertical, 14) .background(background(for: rating), in: RoundedRectangle(cornerRadius: 10, style: .continuous)) .foregroundStyle(foreground(for: rating)) .overlay( RoundedRectangle(cornerRadius: 10, style: .continuous) .stroke(borderColor(for: rating), lineWidth: rating == .good ? 0 : 1) ) } .buttonStyle(.plain) } } .padding(.horizontal, 16) } /// `good` ist die Hero-Action (primary full background) — analog /// zum Web-Default-Klick. Andere bekommen subtle tinted borders. private func background(for rating: Rating) -> Color { switch rating { case .again: CardsTheme.error.opacity(0.06) case .hard: CardsTheme.warning.opacity(0.06) case .good: CardsTheme.primary case .easy: CardsTheme.success.opacity(0.06) } } private func foreground(for rating: Rating) -> Color { switch rating { case .again: CardsTheme.error case .hard: CardsTheme.warning case .good: CardsTheme.primaryForeground case .easy: CardsTheme.success } } private func borderColor(for rating: Rating) -> Color { switch rating { case .again: CardsTheme.error.opacity(0.4) case .hard: CardsTheme.warning.opacity(0.4) case .good: .clear case .easy: CardsTheme.success.opacity(0.4) } } private func kbdBackground(for rating: Rating) -> Color { rating == .good ? CardsTheme.primaryForeground.opacity(0.18) : CardsTheme.muted } private func kbdForeground(for rating: Rating) -> Color { rating == .good ? CardsTheme.primaryForeground.opacity(0.85) : CardsTheme.mutedForeground } private func triggerHaptic(for rating: Rating) { #if canImport(UIKit) let style: UIImpactFeedbackGenerator.FeedbackStyle = rating == .easy ? .heavy : .medium UIImpactFeedbackGenerator(style: style).impactOccurred() #endif } }