Dark Mode preferredColorScheme not updating buttons

100 views Asked by At

Does anyone know why this might be?

I am trying to give my users the option to set dark mode as a preference within the app.

I am using AppStorage to save the users choice and using preferredColorScheme on the Root view to update the entire app.

For the most part this is working and used to work fine. But since iOS 16/17 Buttons or NavigationLinks don't update their color. For example. I have a white system background that changes to black as expected but the text of all Buttons doesn't change and looks hidden on the black background. Yet normal text updates fine.

struct ContentView: View {
    
    @AppStorage("darkMode") var isDarkMode: Bool = false
    
    var body: some View {
        VStack {
            Text("Hello, world!")
            
            Button {
                //
            } label: {
                Text("click me")
            }
            
            Toggle("", isOn: $isDarkMode)
        }
        .padding()
        .preferredColorScheme(isDarkMode ? .dark : nil)
    }
}
2

There are 2 answers

4
Benzy Neez On

I was asking in the comments, how you are styling the buttons. You gave this Button as an example:

Button {} label: {
    Image(systemName: "ellipsis")
        .font(.system(size: 18, weight: .medium))
        .padding(.horizontal, 18)
}

When I try this in isolation, the foreground color is blue. So I suspect, you must be applying something like foregroundStyle(.black) at a higher level. If this is the case, it is not surprising that the foreground color is always black.

To fix, try applying .foregroundStyle(.primary) to the button itself:

Button {} label: {
    // ...
}
.foregroundStyle(.primary)

If that doesn't work, try .tint instead:

Button {} label: {
    // ...
}
.tint(.primary)
0
Dan On

So, it seems when only setting light/dark mode on the Accent Color in the Asset catalog, and then changing the preferred color scheme in the app, the accent color is doing the opposite to what I'd expect. Showing black when it should be showing white and vice versa. I don't know why this is.

The solution I've found is to set .foregroundStyle(.accent) on each view that uses the accent colour.

If anyone has a better solution please let me know.