Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2026 DesignSwiftUI & UI Frameworks

WWDC26 · 18 min · Design / SwiftUI & UI Frameworks

Compose advanced graphics effects with SwiftUI

Discover how to craft rich, custom experiences by creatively composing SwiftUI layout and graphics APIs. We’ll show you how to break down complex designs and use a creative pipeline to chain simple building blocks together. Learn how to draw with layer shaders, animate with timelines, and anchor views with alignment guides.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

  • 0:00 — Introduction
  • 1:40 — Design breakdown
  • 4:11 — Cover art and shader effects
  • 11:07 — Driving animation with time
  • 12:00 — Time-synced transcript view
  • 13:18 — Floating timestamps with alignment guides
  • 16:16 — Creative pipelines
  • 17:13 — Next steps

Code shown on screen · 17 snippets

Cover art image swift · at 4:18 ↗
Image("CoverArt")
Blurred cover art image swift · at 4:24 ↗
Image("CoverArt")
    .blur(radius: 30)
Applying layer effect in SwiftUI swift · at 7:09 ↗
GeometryReader { proxy in
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(),
            maxSampleOffset: .zero
        )
}
.ignoresSafeArea()
Writing layer effect shader in Metal cpp · at 7:21 ↗
[[stitchable]] half4 backgroundWarp(
    float2 position, SwiftUI::Layer layer
) {
    return layer.sample(position);
}
Metal shader with offset parameter cpp · at 7:39 ↗
[[stitchable]] half4 backgroundWarp(
    float2 position, SwiftUI::Layer layer,
    float2 offset
) {
    return layer.sample(position + offset);
}
SwiftUI layer effect with offset parameter swift · at 7:55 ↗
GeometryReader { proxy in
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(
               .float2(.init(x: 0, y: 0))
            ),
            maxSampleOffset: .zero
        )
}
.ignoresSafeArea()
SwiftUI layer effect with full-width offset swift · at 8:04 ↗
GeometryReader { proxy in
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(
               .float2(.init(x: proxy.size.width, y: 0))
            ),
            maxSampleOffset: .zero
        )
}
.ignoresSafeArea()
SwiftUI layer effect with noise sampling swift · at 8:37 ↗
GeometryReader { proxy in
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(
                .float2(proxy.size),
                .image(Image("NoiseTexture"))
            ),
            maxSampleOffset: .zero
        )
}
.ignoresSafeArea()
Metal shader with noise sampling cpp · at 8:55 ↗
[[stitchable]] half4 backgroundWarp(
    float2 position, SwiftUI::Layer layer,
    float2 size, texture2d<half> noiseTex
) {
    constexpr sampler s(address::repeat, filter::linear);
    float2 uv = position / size;

    half4 n = noiseTex.sample(s, uv);
    float2 offset = (float2(n.r, n.g) - 0.5) * 200.0;

    return layer.sample(position + offset);
}
Metal shader with domain warping cpp · at 10:22 ↗
[[stitchable]] half4 backgroundWarp(
    float2 position, SwiftUI::Layer layer,
    float2 size, texture2d<half> noiseTex
) {
    constexpr sampler s(address::repeat, filter::linear);
    float2 uv = position / size;

    half4 n = noiseTex.sample(s, uv);

    float2 q = float2(n.r, n.g);
    n = noiseTex.sample(s, uv + q);

    float2 offset = (float2(n.r, n.g) - 0.5) * 200.0;

    return layer.sample(position + offset);
}
SwiftUI layer effect with static visual swift · at 11:16 ↗
GeometryReader { proxy in
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(
                .float2(proxy.size),
                .image(Image("NoiseTexture"))
            ),
            maxSampleOffset: .zero
        )
}
.ignoresSafeArea()
SwiftUI layer effect with animated visual swift · at 11:37 ↗
@State private var startDate = Date.now

TimelineView(.animation) { timeline in
    let elapsed = timeline.date.timeIntervalSince(
        startDate
    )
    CoverArtView()
        .layerEffect(
            ShaderLibrary.backgroundWarp(
                .float2(proxy.size),
                .image(Image("NoiseTexture")),
                .float(elapsed)
            ),
            maxSampleOffset: .zero
        )
}
Basic transcript view swift · at 12:15 ↗
ScrollView {
    LazyVStack(alignment: .leading, spacing: 12) {
        ForEach(sampleTranscript) { line in
                .font(.title)
                .fontWeight(.bold)
        }
    }
}
Time-synced transcript view swift · at 12:33 ↗
@State private var playback = PlaybackState()

ScrollViewReader { scrollProxy in
    ScrollView {
        LazyVStack(alignment: .leading, spacing: 12) {
            ForEach(sampleTranscript) { line in
                Text(line.text)
                    .transcriptLineStyle(isCurrent: 
                        line.id == playback.currentLineIndex
                    )
            }
        }
    }
    .onChange(of: playback.currentLineIndex, { _, i in
        scrollProxy.scrollTo(i, anchor: .center)
    })
}
Overlay with center alignment swift · at 13:53 ↗
Text(line.text)
     .overlay {
          Text(line.formattedTimestamp)
     }
Overlay with bottom leading alignment swift · at 14:06 ↗
Text(line.text)
     .overlay(alignment: .bottomLeading) {
          Text(line.formattedTimestamp)
     }
Overlay with alignment guide override swift · at 14:32 ↗
Text(line.text)
     .overlay(alignment: .bottomLeading) {
          Text(line.formattedTimestamp)
              .alignmentGuide(.bottom) { $0[.top] }
     }

Resources