// // MenuPicker.swift // Tusker // // Created by Shadowfacts on 11/7/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import SwiftUI struct MenuPicker: UIViewRepresentable { typealias UIViewType = UIButton @Binding var selection: Value let options: [Option] var buttonStyle: ButtonStyle = .labelAndIcon private var selectedOption: Option { options.first(where: { $0.value == selection })! } func makeUIView(context: Context) -> UIButton { let button = UIButton() button.showsMenuAsPrimaryAction = true button.setContentHuggingPriority(.required, for: .horizontal) return button } func updateUIView(_ button: UIButton, context: Context) { var config = UIButton.Configuration.borderless() if #available(iOS 16.0, *) { config.indicator = .popup } if buttonStyle.hasIcon { config.image = selectedOption.image } if buttonStyle.hasLabel { config.title = selectedOption.title } button.configuration = config button.menu = UIMenu(children: options.map { opt in let action = UIAction(title: opt.title, subtitle: opt.subtitle, image: opt.image, state: opt.value == selection ? .on : .off) { _ in selection = opt.value } action.accessibilityLabel = opt.accessibilityLabel return action }) button.accessibilityLabel = selectedOption.accessibilityLabel ?? selectedOption.title button.isPointerInteractionEnabled = buttonStyle == .iconOnly } struct Option { let value: Value let title: String let subtitle: String? let image: UIImage? let accessibilityLabel: String? init(value: Value, title: String, subtitle: String? = nil, image: UIImage? = nil, accessibilityLabel: String? = nil) { self.value = value self.title = title self.subtitle = subtitle self.image = image self.accessibilityLabel = accessibilityLabel } } enum ButtonStyle { case labelAndIcon, labelOnly, iconOnly var hasLabel: Bool { switch self { case .labelAndIcon, .labelOnly: return true default: return false } } var hasIcon: Bool { switch self { case .labelAndIcon, .iconOnly: return true default: return false } } } } struct MenuPicker_Previews: PreviewProvider { @State static var value = 0 static var previews: some View { MenuPicker(selection: $value, options: [ .init(value: 0, title: "Zero"), .init(value: 1, title: "One"), .init(value: 2, title: "Two"), ]) } }