Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save juanarzola/580f4428ca0e4e2fe7a831b23767cd14 to your computer and use it in GitHub Desktop.
Save juanarzola/580f4428ca0e4e2fe7a831b23767cd14 to your computer and use it in GitHub Desktop.
Exposes tintColor in the dimmed state to SwiftUI. Use this to adapt any non-accentColor color to the dimmed state.
//
// EnvironmentDimmedTintColorViewModifier.swift
// Learn
//
// Created by Juan Arzola on 3/17/25.
// Copyright © 2025 Juan Arzola. All rights reserved.
//
import SwiftUI
import UIKit
public extension View {
/**
* Exposes to the environment the tint color of the view at the "dimmed" state. While Color.accentColor automatically adapts
* to this color, no other color does. This \.dimmedTintColor environment value helps you adapt any other color to the dimmed state when as well.
*/
func environmentDimmedTintColor() -> some View {
modifier(EnvironmentDimmedTintColorViewModifier())
}
}
private struct EnvironmentDimmedTintColorViewModifier: ViewModifier {
@State private var dimmedTintColor: Color? = nil
func body(content: Content) -> some View {
content
.overlay(
TintColorObserverRepresentable(
originalTint: UIColor(Color.accentColor),
dimmedTintColor: $dimmedTintColor
)
.frame(width: 0, height: 0)
.accessibilityHidden(true)
.allowsHitTesting(false)
)
.environment(\.dimmedTintColor, dimmedTintColor)
}
}
private class TintColorObserver: UIView {
var originalTint: UIColor? = nil
var dimmedTintColor: Binding<Color?> = .constant(nil)
override func tintColorDidChange() {
super.tintColorDidChange()
if let tintColor {
if originalTint != tintColor {
Task { @MainActor in
dimmedTintColor.wrappedValue = Color(tintColor)
}
}
} else if dimmedTintColor.wrappedValue != nil {
Task { @MainActor in
dimmedTintColor.wrappedValue = nil
}
}
}
}
private struct TintColorObserverRepresentable: UIViewRepresentable {
var originalTint: UIColor?
var dimmedTintColor: Binding<Color?>
func makeUIView(context: Context) -> TintColorObserver {
let view = TintColorObserver()
view.originalTint = originalTint
view.dimmedTintColor = dimmedTintColor.projectedValue
return view
}
func updateUIView(_ uiView: TintColorObserver, context: Context) {
uiView.originalTint = originalTint
}
}
// MARK: - Environment
private struct DimmedTintColorKey: EnvironmentKey {
static let defaultValue: Color? = nil
}
public extension EnvironmentValues {
var dimmedTintColor: Color? {
get { self[DimmedTintColorKey.self] }
set { self[DimmedTintColorKey.self] = newValue }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment