swiftui-liquid-glass
SwiftUI Liquid Glass provides APIs for implementing the dynamic translucent material effect introduced in iOS 26 and across Apple platforms. Use this skill when building custom views with glass-morphic backgrounds, interactive glass buttons, glass containers, morphing transitions, or adopting iOS 26 design patterns that require blur, vibrancy, tinting, and touch reactivity beyond standard framework components.
git clone --depth 1 https://github.com/dpearson2699/swift-ios-skills /tmp/swiftui-liquid-glass && cp -r /tmp/swiftui-liquid-glass/skills/swiftui-liquid-glass ~/.claude/skills/swiftui-liquid-glassSKILL.md
# SwiftUI Liquid Glass
Liquid Glass is the dynamic translucent material introduced across Apple platforms
26. Standard SwiftUI bars and presentations adopt it automatically when built with
the current SDK. Reserve custom glass for functional controls and navigation surfaces,
not general content backgrounds.
See [references/liquid-glass.md](references/liquid-glass.md) for the full API reference with additional examples.
## Contents
- [Workflow](#workflow)
- [Core API Summary](#core-api-summary)
- [Code Examples](#code-examples)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## Workflow
Choose the path that matches the request:
### 1. Implement a new feature with Liquid Glass
1. Identify target surfaces (floating controls, custom bars, transient controls).
2. Decide shape, prominence, and whether each element is a real control or static status.
3. Wrap grouped glass elements in a `GlassEffectContainer`.
4. Apply `.glassEffect()` **after** layout and appearance modifiers.
5. Add `.interactive()` only to tappable/focusable elements.
6. Add morphing transitions with `glassEffectID(_:in:)` where the view hierarchy
changes with animation. Put `glassEffectTransition(_:)` on the inserted or
removed glass child, not on the always-present container, and choose the style
using [Morphing & Transitions](#morphing--transitions).
7. Gate with `if #available(iOS 26, *)` and provide a fallback for earlier versions.
### 2. Improve an existing feature with Liquid Glass
1. Find custom control or navigation backgrounds that can be replaced with `.glassEffect()`.
2. Wrap sibling glass elements in `GlassEffectContainer` for blending and performance.
3. Replace custom glass-like buttons with `.buttonStyle(.glass)`, `.buttonStyle(.glassProminent)`, or configurable styles such as `.buttonStyle(.glass(.clear))`. Use `.glass(_:)` when the button needs a specific tint or variant; reserve `.glassProminent` for high-emphasis primary actions.
4. Add morphing transitions where animated insertion/removal occurs.
### 3. Review existing Liquid Glass usage
Trace each effect through content/control ownership, layout order, container scope, interactivity, transitions, availability, accessibility settings, and fallback. Restore the same UI fixture and rerun the checklist after each correction.
## Core API Summary
### glassEffect(_:in:)
Applies Liquid Glass behind a view. Default: `.regular` variant in a `Capsule` shape.
```swift
nonisolated func glassEffect(
_ glass: Glass = .regular,
in shape: some Shape = DefaultGlassEffectShape()
) -> some View
```
### Glass struct
| Property / Method | Purpose |
|---|---|
| `.regular` | Standard glass material |
| `.clear` | Clear variant; add dimming/contrast treatment when legibility needs it |
| `.identity` | No visual effect (pass-through) |
| `.tint(_:)` | Add a color tint for prominence |
| `.interactive(_:)` | React to touch and pointer interactions |
Chain them: `.regular.tint(.blue).interactive()`
### GlassEffectContainer
Wraps multiple glass views for shared rendering, blending, and morphing.
```swift
GlassEffectContainer(spacing: 24) {
// child views with .glassEffect()
}
```
The `spacing` controls when nearby glass shapes begin to blend. Match or exceed
the interior layout spacing so shapes merge during animated transitions but remain
separate at rest.
### Morphing & Transitions
| Modifier | Purpose |
|---|---|
| `glassEffectID(_:in:)` | Stable identity for morphing during view hierarchy changes |
| `glassEffectUnion(id:namespace:)` | Merge multiple views into one glass shape |
| `glassEffectTransition(_:)` | Control how glass appears/disappears |
Transition decision: use `.matchedGeometry` for nearby effects inside the container's
spacing; use `.materialize` for distant insertion/removal or when no geometry match
should occur; use `.identity` only when no transition animation is wanted.
### Button Styles
```swift
Button("Action") { }
.buttonStyle(.glass) // standard glass button
Button("Primary") { }
.buttonStyle(.glassProminent) // prominent glass button
Button("Media") { }
.buttonStyle(.glass(.clear)) // configurable variant; verify contrast
```
### Related iOS 26 APIs
| API | Use |
|---|---|
| `scrollEdgeEffectStyle` | Configure a scroll boundary's visual treatment. |
| `backgroundExtensionEffect` | Extend one background under safe-area edges with mirrored blur. |
| `ToolbarSpacer` | Create a visual break between toolbar items. |
See the corresponding sections in
[references/liquid-glass.md](references/liquid-glass.md) for signatures and examples.
## Code Examples
### Glass button with availability gate
```swift
if #available(iOS 26, *) {
Button("Show Status") { showStatusDetails() }
.buttonStyle(.glass)
} else {
Button("Show Status") { showStatusDetails() }
.buttonStyle(.bordered)
}
```
### Grouped glass shapes in a container
```swift
let symbols = ["pencil", "eraser.fill", "lasso"]
GlassEffectContainer(spacing: 24) {
HStack(spacing: 24) {
ForEach(symbols, id: \.self) { symbol in
Image(systemName: symbol)
.frame(width: 56, height: 56)
.glassEffect()
}
}
}
```
### Nearby morphing transition
```swift
@State private var isExpanded = false
@Namespace private var ns
var body: some View {
GlassEffectContainer(spacing: 40) {
HStack(spacing: 40) {
Image(systemName: "pencil")
.frame(width: 80, height: 80)
.glassEffect()
.glassEffectID("pencil", in: ns)
if isExpanded {
Image(systemName: "eraser.fill")
.frame(width: 80, height: 80)
.glassEffect()
.glassEffectID("eraser", in: ns)
.glassEffectTransition(.matchedGeometry)
}
}
}
Button("Toggle")Discover and configure Bluetooth and Wi-Fi accessories using AccessorySetupKit. Use when presenting a privacy-preserving accessory picker, defining discovery descriptors for BLE or Wi-Fi devices, handling accessory session events, migrating from CoreBluetooth permission-based scanning, or setting up accessories without requiring broad Bluetooth permissions.
Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets.
Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement.
Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, system Stop and AlarmButton secondary actions, authorization, state observation, countdown widget-extension handoff, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.
Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store Connect experiences, size/capability constraints, NSUserActivity routing, SKOverlay promotion, App Group/keychain handoff, ephemeral notifications, location confirmation, and full-app migration. Use when creating App Clips or wiring App Clip invocation, experience configuration, or full-app handoff.
Implement App Intents for Siri, Shortcuts, Spotlight, widgets, Control Center, and Apple Intelligence on iOS. Covers AppIntent actions, AppEntity and EntityQuery models, AppShortcutsProvider phrases, IndexedEntity Spotlight indexing, WidgetConfigurationIntent, SnippetIntent, and assistant schemas. Use when exposing app actions or entities to system surfaces.
Optimize App Store product pages for search visibility and conversion. Use for App Store Optimization (ASO), keyword research, app name/subtitle/keyword-field strategy, conversion-focused descriptions and promotional text, screenshot captions and ordering, Custom Product Pages with assigned search keywords, In-App Events, Product Page Optimization tests, localized metadata, ratings/review strategy, and in-app review prompt timing with RequestReviewAction or AppStore.requestReview. Also use when routing ASO vs App Store review, privacy/ATT, or StoreKit implementation boundaries.
Audits App Store submission readiness and rejection risk across current review guidelines, PrivacyInfo.xcprivacy and required-reason APIs, privacy labels, ATT, StoreKit payments, metadata, entitlements, widgets, and Live Activities. Use when preparing a submission, responding to rejection, reconciling privacy evidence, or separating upload blockers from cleanup.