[Idea] - Toggle Button Tray
Hello,
I have an idea for a Toggle Button Tray. For now, to add a button to active / deactivate a feature we go with a @State variable and a toggle code.
Maybe it is worth creating a specific Toggle button with a binding to a State variable.
Actual
@State private var displayOnlyFavorite = false
let favoriteItem = BDButtonTrayItem(title: "Favorite", systemImage: "star") { item in
item.systemImage = self.displayOnlyFavorite ? "star" : "star.fill"
self.displayOnlyFavorite.toggle()
self.reloadLocations()
}
favoriteItem.activeColor = Color.yellow
favoriteItem.inactiveColor = Color.yellow
Idea
@State private var displayOnlyFavorite = false
let favoriteItem = BDButtonTrayToggleItem(title: "Favorite", systemImage: "star", systemImageToggled: "star.fill", toggle: $displayOnlyFavorite) { item in
self.reloadLocations()
}
Nicolas
Hi Nicolas,
This is actually a good idea. I can see the use case and how you want the item to react to @State variable.
However, BDButtonTrayItem is a view model to render BDButtonTrayItemView behind the scene so I think having several of similar objects is not a good idea. At least that is what I think at the moment, from a framework perspective.
But I hear you, so to allow extendibility, what I would consider doing instead, is to either:
- Create a
BDButtonTrayItemProtocolwhere developers can conform to and create their own custom item or - Remove
finalfrompublic final class BDButtonTrayItemso that developers can subclass and add more functionalities themselves.
Thank you for the idea, it allows me to refine the framework and make it better.
I would vote for the protocol BDButtonTrayItemProtocol, with a default implementation for the Toggle case.
Now that I think about it, protocol might not work well because we cannot constrain a property to be, say @Published
For example
protocol BDButtonTrayItemProtocol: ObservableObject {
// can constrain to have setter and getter
// but cannot constraint that it must be an @Published var σ(^_^;)
var title: String { set get }
}
I think remove final is probably a way to go. In your case, you can do something like this.
class FavoriteButtonTrayItem: BDButtonTrayItem {
@Binding var favorited: Bool {
didSet { systemImage = favorited ? "star.fill" : "star" }
}
init(favorite: Binding<Bool>) {
_favorited = favorite
super.init(...)
}
}