We can present the color picker in swiftUI easily.
ColorPicker("", selection: $selectedColor)
However, in my macOS app it looks ridiculous as it opens as a standalone view and is disconnected from the app.
What I would like to achieve is by tapping a button, color picker opens in popover, the same way as it opens in the Preview app.
You might be looking for a NSColorWell
with the minimal
style.
It looks like this:
Here I have wrapped this in a NSViewRepresentable
:
struct MyColorPicker: NSViewRepresentable {
@Binding var color: Color
func makeNSView(context: Context) -> NSColorWell {
let colorWell = NSColorWell(style: .minimal)
colorWell.color = NSColor(color)
context.coordinator.startObservingColorChange(of: colorWell)
return colorWell
}
func updateNSView(_ nsView: NSColorWell, context: Context) {
nsView.color = NSColor(color)
context.coordinator.colorDidChange = {
color = Color(nsColor: $0)
}
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
@MainActor
class Coordinator: NSObject {
var colorDidChange: ((NSColor) -> Void)?
private var cancellable: AnyCancellable?
func startObservingColorChange(of colorWell: NSColorWell) {
cancellable = colorWell.publisher(for: \.color).sink { [weak self] in
self?.colorDidChange?($0)
}
}
}
}
Usage:
struct ContentView: View {
@State var color: Color = .white
var body: some View {
VStack {
color
MyColorPicker(color: $color).fixedSize()
}
.padding()
}
}