diff --git a/Sources/FluentUI_common/Core/Extensions/View+Modifiers.swift b/Sources/FluentUI_common/Core/Extensions/View+Modifiers.swift index 74795f678..b9078a67b 100644 --- a/Sources/FluentUI_common/Core/Extensions/View+Modifiers.swift +++ b/Sources/FluentUI_common/Core/Extensions/View+Modifiers.swift @@ -13,6 +13,28 @@ public extension View { func applyFluentShadow(shadowInfo: ShadowInfo) -> some View { modifier(ShadowModifier(shadowInfo: shadowInfo)) } + + /// Backwards compatible wrapper of the iOS26+ .glassEffect modifier + /// - On iOS 26 / macOS 26 and newer: applies `glassEffect()`. + /// - On older OSes and unsupported platforms: applies a background with `.regularMaterial` and `shadow08`, with the exception of older macOS versions where no background is applied + /// - Parameters: + /// - interactive: Whether the glass effect should be interactive. + /// - tint: The tint color to apply to the glass effect. + /// - shape: The shape to apply the glass effect to. + /// - Returns: The modified view with the glass effect applied. + @ViewBuilder func fluentGlassEffect( + interactive: Bool = false, + tint: Color? = nil, + in shape: T = Capsule() + ) -> some View where T: Shape { + self.modifier( + FluentGlassEffectModifier( + interactive: interactive, + tint: tint, + shape: shape + ) + ) + } } /// ViewModifier that applies both shadows from a ShadowInfo @@ -36,3 +58,34 @@ private struct ShadowModifier: ViewModifier { } } +private struct FluentGlassEffectModifier: ViewModifier { + @Environment(\.fluentTheme) private var fluentTheme: FluentTheme + + let interactive: Bool + let tint: Color? + let shape: T + + func body(content: Content) -> some View { + #if os(visionOS) || compiler(<6.2) + content + .background(.regularMaterial, in: shape) + .applyFluentShadow(shadowInfo: fluentTheme.shadow(.shadow08)) + #elseif os(macOS) + if #available(macOS 26, *) { + content + .glassEffect(.regular.interactive(interactive).tint(tint), in: shape) + } else { + content // don't add any background + } + #else + if #available(iOS 26, *) { + content + .glassEffect(.regular.interactive(interactive).tint(tint), in: shape) + } else { + content + .background(.regularMaterial, in: shape) + .applyFluentShadow(shadowInfo: fluentTheme.shadow(.shadow08)) + } + #endif + } +}