Unable to control SwiftUI macOS list selection styling

Viewed 174

On macOS running natively (not in catalyst mode), a SwiftUI List with selection enabled has multiple style states controlled by what appear to be implicit variables that I can't seem to access. As a result, a custom foregroundColor on a View in a List behaves erratically. In particular, given the below example, there should in theory be 3 total styling states, but in reality there are effectively 5 possible styling states of Item 2:

State Foreground color Background color Screenshot
A. Item 2 is selected and window is active White Accent d
B. Item 2 is selected and window is inactive *Black (but should be faded blue) Gray d
C. Item 2 is not selected and window is active (Item 2 also looks the same for an inactive window) Blue None d
D. Item 2 was just clicked, but we need to wait ~300ms before it becomes selected *Blue (but should be white) Accent d
E. Item 2 was previously selected, a new item is clicked, but we need to wait ~300ms before the new item becomes selected *Black (but should be blue) None d

How can I control the foreground color in states B, D, and E? For cases D and E, it seems that there's some kind of built in debouncing on the macOS List selection that causes a brief delay after first clicking before actually becoming selected. Is there something like a not-debounced isHighlighted property? Clearly the built in system is using something like this as the non-custom list label colors immediately switch from black to white regardless of the debounce, as in Item 1 in state 5 above. For case B perhaps there's a different color property instead of foregroundColor that I need to use?

Any suggestions are much appreciated!

Minimally reproducable example (run on macOS native, not catalyst):

@main
struct ExampleApp: App {
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

struct ContentView: View {
  @State private var selected: String?
  
  var body: some View {
    NavigationView {
      List {
        NavigationLink(destination: Text("Detail 1"), tag: "1", selection: $selected) {
          Label("Item 1", systemImage: "tag")
        }
        NavigationLink(destination: Text("Detail 2"), tag: "2", selection: $selected) {
          Label {
            Text("Item 2")
              .foregroundColor(selected == "2" ? nil : .blue)
          } icon: {
            Image(systemName: "tag")
              .foregroundColor(selected == "2" ? nil : .blue)
          }
        }
      }
      .toolbar {
        Button {
        } label: {
          Image(systemName: "sidebar.left")
        }
      }
    }
    .navigationTitle("Test")
    .listStyle(.sidebar)
  }
}

Style state screenshots above all come from this example:

enter image description here

0 Answers
Related