BDUIKnit icon indicating copy to clipboard operation
BDUIKnit copied to clipboard

[Idea] - Toggle Button Tray

Open satan87 opened this issue 5 years ago • 3 comments

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

satan87 avatar May 03 '20 20:05 satan87

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 BDButtonTrayItemProtocol where developers can conform to and create their own custom item or
  • Remove final from public final class BDButtonTrayItem so 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.

bdaralan avatar May 03 '20 21:05 bdaralan

I would vote for the protocol BDButtonTrayItemProtocol, with a default implementation for the Toggle case.

satan87 avatar May 03 '20 22:05 satan87

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(...)
    }
}

bdaralan avatar May 03 '20 22:05 bdaralan