banner: key by value so tip fades out on dismiss
The banner sits in a single if-let slot; without an identity key, clearing a tip that was covering a network/offline banner swapped content in place with no transition (instantly vanishing). Keying the banner by its value (.id) makes every change — tip→network or tip→nil — run the shared removal transition, so the tip slides up and fades out when it auto-dismisses or is tapped.
This commit is contained in:
@@ -5,7 +5,7 @@ import WidgetKit
|
|||||||
/// The single floating notification banner. Network/offline state and tip
|
/// The single floating notification banner. Network/offline state and tip
|
||||||
/// outcomes all funnel through ONE style and render via the same chrome in
|
/// outcomes all funnel through ONE style and render via the same chrome in
|
||||||
/// ContentView — never pushing layout, always overlaid.
|
/// ContentView — never pushing layout, always overlaid.
|
||||||
enum AppBanner: Equatable {
|
enum AppBanner: Hashable {
|
||||||
case offlineDump(date: String)
|
case offlineDump(date: String)
|
||||||
case connectionProblem
|
case connectionProblem
|
||||||
case tip(TipStore.TipOutcome)
|
case tip(TipStore.TipOutcome)
|
||||||
@@ -491,6 +491,10 @@ struct ContentView: View {
|
|||||||
// main content so it doesn't cover or block the list/pill
|
// main content so it doesn't cover or block the list/pill
|
||||||
// beneath it.
|
// beneath it.
|
||||||
floatingBanner(banner)
|
floatingBanner(banner)
|
||||||
|
// Key by value so ANY change (tip→network, tip→nil)
|
||||||
|
// runs the removal transition (fade/slide-out) instead
|
||||||
|
// of silently swapping content in place.
|
||||||
|
.id(banner)
|
||||||
.padding(.top, geo.safeAreaInsets.top + 10)
|
.padding(.top, geo.safeAreaInsets.top + 10)
|
||||||
.transition(.asymmetric(
|
.transition(.asymmetric(
|
||||||
insertion: .move(edge: .top).combined(with: .opacity),
|
insertion: .move(edge: .top).combined(with: .opacity),
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ final class TipStore: ObservableObject {
|
|||||||
]
|
]
|
||||||
|
|
||||||
/// A banner outcome: the exact copy to show plus its icon + tint.
|
/// A banner outcome: the exact copy to show plus its icon + tint.
|
||||||
struct TipOutcome: Equatable {
|
struct TipOutcome: Hashable {
|
||||||
let message: String
|
let message: String
|
||||||
let icon: String
|
let icon: String
|
||||||
let tint: Color
|
let tint: Color
|
||||||
|
|||||||
Reference in New Issue
Block a user