@reindebock Yes, that's a good workaround for vertical sliders. Instead of including the whole SwiftUIIntrospect library, one can also just wrap the NSSlider in a NSViewRepresentable, (as that library presumably does under the hood, along the lines shown for iOS at https://swdevnotes.com/swift/2021/how-to-customise-the-slider-in-swiftui/#documentTop#use-uislider-from-uikit )
Here's a version of that for MacOS:
import SwiftUI
struct VerticalSlider: NSViewRepresentable {
@Binding var value: Double
var bounds: ClosedRange<Double>
class Coordinator: NSObject {
var value: Binding<Double>
var bounds: ClosedRange<Double>
init(value: Binding<Double>, bounds: ClosedRange<Double> = 0...1) {
self.value = value
self.bounds = bounds
}
@objc func valueChanged(_ sender: NSSlider) {
self.value.wrappedValue = sender.doubleValue
}
}
func makeCoordinator() -> VerticalSlider.Coordinator {
Coordinator(value: $value)
}
func makeNSView(context: Context) -> NSSlider {
let slider = NSSlider(frame: .zero)
slider.isVertical = true
slider.minValue = bounds.lowerBound
slider.maxValue = bounds.upperBound
slider.doubleValue = value
slider.action = #selector(Coordinator.valueChanged(_:))
slider.target = context.coordinator
return slider
}
func updateNSView(_ nsView: NSSlider, context: Context) {
nsView.doubleValue = value
}
}
struct SliderTestView: View {
@State var speed = 5.0
var body: some View {
VStack() {
Text("\(speed)")
VerticalSlider(value: $speed, bounds: 1.0...10.0)
.onChange(of: speed) { speed in
print("\(speed)")
}
.frame(width: 50, height: 200)
}
}
}
#Preview {
SliderTestView()
}