# Tooltip System Refactoring ## Overview The tooltip management system has been refactored from game-specific implementations to a generic, reusable system in CasinoKit. ## Problem The original implementation had several issues: - **Verbose**: Each game had duplicate `TooltipConfig` structs and complex state management - **Not scalable**: Adding new tooltips required significant boilerplate - **Repetitive logic**: Similar code duplicated across Blackjack and Baccarat - **Difficult to maintain**: Changes required updates in multiple places ## Solution Created a centralized `TooltipManager` class in CasinoKit that: - Manages tooltip state generically - Automatically handles dismiss tracking - Ensures only one tooltip shows at a time - Integrates seamlessly with `OnboardingState` ## New Components ### 1. `TooltipConfig` (CasinoKit) A simple struct defining tooltip properties: ```swift public struct TooltipConfig: Equatable { public let key: String public let message: String public let icon: String public let position: ContextualTooltip.TooltipPosition } ``` ### 2. `TooltipManager` (CasinoKit) An `@Observable` class that manages tooltip lifecycle: ```swift @Observable @MainActor public final class TooltipManager { private let onboarding: OnboardingState public var currentTooltip: TooltipConfig? public func show( key: String, message: String, icon: String = "lightbulb.fill", position: ContextualTooltip.TooltipPosition = .bottom, delay: TimeInterval = 1.0 ) public func dismiss() } ``` **Key Features:** - Automatic dismiss tracking via `didSet` on `currentTooltip` - Delayed presentation with cancellation if hint already shown - Respects `OnboardingState.shouldShowHint()` checks - Single source of truth for current tooltip ### 3. `dynamicTooltip` View Modifier (CasinoKit) A convenient view modifier that displays tooltips: ```swift public extension View { func dynamicTooltip(_ manager: TooltipManager) -> some View } ``` ## Usage in Games ### Before (Verbose) ```swift // State variables for each tooltip @State private var showBettingHint = false @State private var showDealHint = false @State private var showActionsHint = false // Separate struct definition private struct TooltipConfig { let key: String let message: String let icon: String let position: ContextualTooltip.TooltipPosition } // Complex state with tracking @State private var currentTooltip: TooltipConfig? { didSet { if let oldValue = oldValue, oldValue.key != currentTooltip?.key { state.onboarding.markHintShown(oldValue.key) } } } // Generic helper with lots of parameters private func showTooltip(key: String, message: String, icon: String, position: ContextualTooltip.TooltipPosition, delay: TimeInterval) { Task { @MainActor in try? await Task.sleep(for: .seconds(delay)) guard state.onboarding.shouldShowHint(key) else { return } withAnimation(.spring(duration: Design.Animation.springDuration)) { currentTooltip = TooltipConfig(key: key, message: message, icon: icon, position: position) } } } // Complex overlay in view body .overlay { if let tooltip = currentTooltip { VStack { // ... positioning logic ContextualTooltip( message: tooltip.message, icon: tooltip.icon, position: tooltip.position, onDismiss: { state.onboarding.markHintShown(tooltip.key) withAnimation(.spring(duration: Design.Animation.springDuration)) { currentTooltip = nil } } ) // ... more positioning } } } ``` ### After (Clean) ```swift // Single state variable @State private var tooltipManager: TooltipManager? // Initialize in onAppear .onAppear { tooltipManager = TooltipManager(onboarding: state.onboarding) } // Simple show calls private func showBettingHint() { tooltipManager?.show( key: "bettingZone", message: "Select a chip and tap here to bet", icon: "hand.tap.fill", position: .bottom, delay: 1.0 ) } // One-line view modifier .dynamicTooltip(tooltipManager ?? TooltipManager(onboarding: state.onboarding)) ``` ## Benefits 1. **Reduced code**: ~70 lines of boilerplate eliminated per game 2. **Better scalability**: Adding new tooltips is now trivial 3. **Single source of truth**: All tooltip logic in CasinoKit 4. **Easier maintenance**: Changes only need to be made in one place 5. **Reusable**: Any new game can use `TooltipManager` with minimal setup ## Files Changed ### CasinoKit - **Created**: `Sources/CasinoKit/Models/TooltipManager.swift` - **Updated**: `Sources/CasinoKit/Exports.swift` (added TooltipManager export) - **Updated**: `README.md` (added TooltipManager documentation) ### Blackjack - **Updated**: `Views/Game/GameTableView.swift` - Removed local `TooltipConfig` struct - Removed `currentTooltip` @State with didSet - Removed generic `showTooltip()` helper - Added `@State private var tooltipManager: TooltipManager?` - Simplified tooltip show methods - Replaced complex overlay with `.dynamicTooltip()` modifier ### Baccarat - **Updated**: `Views/Game/GameTableView.swift` - Same changes as Blackjack ## Migration Guide To use `TooltipManager` in a new game: 1. **Add state variable:** ```swift @State private var tooltipManager: TooltipManager? ``` 2. **Initialize in onAppear:** ```swift .onAppear { tooltipManager = TooltipManager(onboarding: gameState.onboarding) } ``` 3. **Apply view modifier:** ```swift .dynamicTooltip(tooltipManager ?? TooltipManager(onboarding: gameState.onboarding)) ``` 4. **Show tooltips:** ```swift tooltipManager?.show( key: "uniqueKey", message: "Your hint text", icon: "lightbulb.fill", position: .bottom, delay: 1.0 ) ``` ## Testing Both Blackjack and Baccarat have been built and tested successfully with the new system. ```bash # Blackjack xcodebuild -workspace CasinoGames.xcworkspace -scheme Blackjack \ -configuration Debug -destination 'platform=iOS Simulator,id=...' build # ✅ BUILD SUCCEEDED # Baccarat xcodebuild -workspace CasinoGames.xcworkspace -scheme Baccarat \ -configuration Debug -destination 'platform=iOS Simulator,id=...' build # ✅ BUILD SUCCEEDED ``` ## Future Enhancements Potential improvements: - **Tooltip queue**: Allow queueing multiple tooltips - **Positioning hints**: Auto-detect best position based on screen space - **Animation customization**: Per-tooltip animation styles - **Analytics**: Track which tooltips are most helpful