Lab 083 – Feathered Glass Title Card

A mock up of a title card for the Shared Visions Project.

We can add a feathered effect to glass backgrounds. This labs uses that concept to create a card that we could use for titles and chapters. Learn more about using glassBackgroundEffect on your views.Example:

Text("Feathered Glass Background Effect")
  .font(.extraLargeTitle)
  .glassBackgroundEffect(.feathered(padding: 36, softEdgeRadius: 3), displayMode: .always)

This looks great with a little animation. Here we animate softEdgeRadius over 4 seconds to create a breathing effect around the edges.

animated title card

Lab Code

private struct TitleWidthKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) }
}

struct Lab083: View {
    @State private var progress: CGFloat = 0.0
    @State private var titleWidth: CGFloat = 0

    var body: some View {
        VStack(spacing: 18) {

            Text("Shared Visions")
                .font(.extraLargeTitle)
                .shadow(radius: 12)
                .fixedSize() // measure intrinsic width, not expanded width
                .background(
                    GeometryReader { g in
                        Color.clear.preference(key: TitleWidthKey.self, value: g.size.width)
                    }
                )

            Text("Stories from the Apple Vision Pro community.")
                .shadow(radius: 12)
                .multilineTextAlignment(.center)
                .frame(width: titleWidth) // matches the title’s width
                .lineLimit(1)
                .minimumScaleFactor(0.5)

            Button(action: {}, label: {
                Label("Explore", systemImage: "heart.fill")
            })
            .shadow(radius: 12)
        }
        .onPreferenceChange(TitleWidthKey.self) { titleWidth = $0 }
        .padding(18)
        .glassBackgroundEffect(
            .feathered(
                padding: 36,
                softEdgeRadius: 4 + (6 * progress)
            ),
            displayMode: .always
        )
        .onAppear {
            withAnimation(.easeInOut(duration: 4.0).repeatForever()) {
                progress = 1.0
            }
        }
        .persistentSystemOverlays(.hidden)
    }
}

Support our work so we can continue to bring you new examples and articles.

Download the Xcode project with this and many more labs from Step Into Vision.

Questions or feedback?