Created
July 16, 2026 17:52
-
-
Save moyerr/fdbef96e6aa1c6a5a7fb3348b07e0bf6 to your computer and use it in GitHub Desktop.
Add ShapeStyle support to @ConentBuilder, allowing for more dynamic custom ShapeStyle implementations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// A ShapeStyle that adapts dynamically based on the environment's ColorScheme | |
| /// | |
| /// This exists as a basic example of how to apply a @ContentBuilder to ShapeStyles | |
| struct AdaptiveStyle<Light: ShapeStyle, Dark: ShapeStyle>: ShapeStyle { | |
| let light: Light | |
| let dark: Dark | |
| @ContentBuilder | |
| func resolve(in environment: EnvironmentValues) -> some ShapeStyle { | |
| if environment.colorScheme == .light { | |
| light | |
| } else { | |
| dark | |
| } | |
| } | |
| } | |
| extension ShapeStyle { | |
| static func adaptive<Dark: ShapeStyle, Light: ShapeStyle>( | |
| light: Light, | |
| dark: Dark | |
| ) -> Self where Self == AdaptiveStyle<Light, Dark> { | |
| .init(light: light, dark: dark) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Augment ContentBuilder with basic functionaly to support ShapeStyle as Content | |
| extension ContentBuilder { | |
| // SwiftUI's built-in _ConditionalContent is explicitly non-Sendable, and ShapeStyle is | |
| // Sendable, so we need to supply our own supporting type for conditionals | |
| enum _ConditionalShapeStyle<True: ShapeStyle, False: ShapeStyle>: ShapeStyle { | |
| case trueContent(True) | |
| case falseContent(False) | |
| func _apply(to shape: inout _ShapeStyle_Shape) { | |
| switch self { | |
| case .trueContent(let content): | |
| content._apply(to: &shape) | |
| case .falseContent(let content): | |
| content._apply(to: &shape) | |
| } | |
| } | |
| } | |
| static func buildOptional<S: ShapeStyle>( | |
| _ component: S? | |
| ) -> _ConditionalShapeStyle<S, Color> { | |
| if let component { | |
| return .trueContent(component) | |
| } else { | |
| return .falseContent(.clear) | |
| } | |
| } | |
| static func buildEither<TrueContent: ShapeStyle, FalseContent: ShapeStyle>( | |
| first: TrueContent | |
| ) -> _ConditionalShapeStyle<TrueContent, FalseContent> { | |
| .trueContent(first) | |
| } | |
| static func buildEither<TrueContent: ShapeStyle, FalseContent: ShapeStyle>( | |
| second: FalseContent | |
| ) -> _ConditionalShapeStyle<TrueContent, FalseContent> { | |
| .falseContent(second) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment