SwiftUI List on maCOS: highlighting content in the selected row?

Hello all,

In a SwiftUI List, when a row is selected, a blue selection is drawn in the selection, and foreground Text with the default primary color is automatically made white. For other views with custom colors, I'd like to be able to make sure they become tinted white to match the system apps. For example, see the blue dot on the selected row:

Example code:

List(selection: $selection) {
    ForEach(0..<4) { index in
        HStack {
            Image(systemName: "circle.fill")
                .foregroundColor(.blue)
            Text("Test")
        }
        .tag(index)
    }
}

With NSTableCellView, there is the backgroundStyle property. I've searched all of the available environment variables, and couldn't find anything appropriate. I have also tried manually including an isSelected binding on a view for each row, but the selection binding is not updated by List until mouse-up, while the highlight is updated on mouse-down and drag, so this results in a flickery appearance and is not right either.

Any tips on how to achieve the correct result here? Thanks! 🙏

There is a modifier called listItemTint(_:) that seems like it should do what you are asking for.

It's worth checking out, but I believe the behaviour changed in iOS 15 for some reason, intentionally or not.

This is a macOS related thing. I have chased this forever in vain. This is akin to NSCell.isHighlighted or NSCell.backgroundStyle

I for sure want to use some special colors when not in highlight mode. A cell will be first highlighted in mouse down and than eventually selected on mouse up. So apple has to provide an API or an environment value to indicate to our row view that is highlighted or not.

Maybe @eskimo can look up the source for this and shed some deep insight.

This is a macOS issue, ie: NSView.BackgroundStyle We have no way of telling inside a SwiftUI view that we are just highlighted. The user can highlight/un-highlight a bunch of rows during a mouse down, mouse drag sequence, but they are not selected yet until you release the mouse.

A very cool AppKit feature. Maybe @Eskimo can Shed some deep insights on how this migrates to SwiftUI.

This isn't a built in feature, but I created an environment key called isSelected.

The Environment is how most of the built in view modifiers work under the hood.

struct SelectedEnvironmentKey: EnvironmentKey {
    static var defaultValue: Bool = false
}

extension EnvironmentKeys {
    var isSelected: Bool {
        get { self[SelectedEnvironmentKey.self] }
        set { self[SelectedEnvironmentKey.self] = newValue }
    }
}

then in the ForEach you can do:

ForEach { myModel in
    RowView(model: myModel)
        .envrionment(\.isSelected, selection.contains(model))
}

Then in your RowView

struct RowView: View {
    @Environment(\.isSelected) private var isSelected


    var body: some View {
        // My views
             .background {
                   if isSelected {
                        return Color.blue
                   }
              }
    }
}
SwiftUI List on maCOS: highlighting content in the selected row?
 
 
Q