From apple-skills
Provides API reference and design guidelines for Liquid Glass in iOS 26+ SwiftUI apps: glass effects, navigation patterns, GlassEffect modifiers, principles to avoid generic designs.
npx claudepluginhub vabole/apple-skills --plugin apple-skillsThis skill uses the workspace's default tool permissions.
Create distinctive, Apple Design Award-worthy iOS applications using the Liquid Glass design system. This skill pushes beyond generic implementations toward memorable, polished interfaces that feel genuinely designed—not AI-generated.
adopting-liquid-glass.mdadopting-liquid-glass.videos.mdapplying-to-custom-views.mdapplying-to-custom-views.videos.mdglass.mdglasseffect.mdglasseffectcontainer.mdlandmarks-activity-badges.mdlandmarks-background-extension.mdlandmarks-building-app.mdlandmarks-horizontal-scrolling.mdlandmarks-toolbar-glass.mdliquid-glass-overview.mdreference.mdview-glasseffect.mdview-glasseffectid.mdview-scrolledgeeffectstyle.mdGuides implementation of Apple's Liquid Glass design system for iOS 26+ UI using SwiftUI glassEffect, GlassEffectContainer, morphing transitions, UIKit NSGlassEffectView, with fallbacks, accessibility, and performance patterns.
Guides implementing, reviewing, debugging, and optimizing Apple's Liquid Glass UI effects with WWDC 2025 principles, APIs, troubleshooting, and expert review criteria.
Implements iOS 26 Liquid Glass effects in SwiftUI, UIKit, and WidgetKit for dynamic blur, reflections, interactive deformation, and morphing transitions between glass elements.
Share bugs, ideas, or general feedback.
Create distinctive, Apple Design Award-worthy iOS applications using the Liquid Glass design system. This skill pushes beyond generic implementations toward memorable, polished interfaces that feel genuinely designed—not AI-generated.
Before writing code, commit to a distinctive aesthetic direction:
| Principle | Description |
|---|---|
| Hierarchy | Controls float above content. Glass frames, never obscures. Content is king. |
| Harmony | Software design aligns with hardware. Concentric corners. Fluid gestures. |
| Consistency | Adapt fluidly across iPhone, iPad, Mac. Same identity, contextual expression. |
These are hallmarks of generic AI-generated iOS design:
import SwiftUI
// Simple glass application
Text("Action")
.padding()
.glassEffect() // .regular variant, .capsule shape
// With explicit parameters
Button("Confirm") { }
.padding()
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 12), isEnabled: true)
| Variant | Use Case |
|---|---|
.regular | Toolbars, nav bars, tab bars, standard controls |
.clear | Floating controls over media (photos, maps, video) |
.identity | Conditional disable: glassEffect(isActive ? .regular : .identity) |
// Semantic tinting (for primary actions only)
.glassEffect(.regular.tint(.accentColor))
// Interactive behaviors (scaling, shimmer, touch illumination)
.glassEffect(.regular.interactive())
// Combined
.glassEffect(.regular.tint(.blue).interactive())
// Standard shapes
.glassEffect(.regular, in: .capsule)
.glassEffect(.regular, in: .circle)
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
// Container-concentric (matches device/container corners)
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))
Glass cannot sample other glass. Use containers for multiple glass elements:
GlassEffectContainer(spacing: 30) {
HStack(spacing: 20) {
ForEach(actions) { action in
Button(action.title, systemImage: action.icon) { }
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
}
}
}
struct ExpandableActions: View {
@State private var isExpanded = false
@Namespace private var namespace
var body: some View {
GlassEffectContainer(spacing: 30) {
VStack(spacing: 30) {
if isExpanded {
ActionButton(icon: "rotate.right")
.glassEffectID("rotate", in: namespace)
}
HStack(spacing: 30) {
if isExpanded {
ActionButton(icon: "slider.horizontal.3")
.glassEffectID("adjust", in: namespace)
}
Button {
withAnimation(.bouncy) { isExpanded.toggle() }
} label: {
Image(systemName: isExpanded ? "xmark" : "plus")
.frame(width: 56, height: 56)
}
.glassEffect(.regular.tint(.accentColor).interactive())
.glassEffectID("toggle", in: namespace)
if isExpanded {
ActionButton(icon: "crop")
.glassEffectID("crop", in: namespace)
}
}
if isExpanded {
ActionButton(icon: "wand.and.stars")
.glassEffectID("enhance", in: namespace)
}
}
}
}
}
TabView {
Tab("Home", systemImage: "house") {
HomeView()
}
Tab("Search", systemImage: "magnifyingglass") {
SearchView()
}
Tab("Profile", systemImage: "person") {
ProfileView()
}
}
// Tab bar now floats, reacts to background, collapses on scroll
.toolbar {
ToolbarItemGroup(placement: .topBarTrailing) {
Button("Edit", systemImage: "pencil") { }
Button("Share", systemImage: "square.and.arrow.up") { }
}
ToolbarSpacer(.flexible, placement: .topBarTrailing)
ToolbarItem(placement: .topBarTrailing) {
Button("Done", systemImage: "checkmark") { }
.tint(.accentColor)
}
}
struct ContentView: View {
@State private var showSettings = false
@Namespace private var namespace
var body: some View {
NavigationStack {
ContentView()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Settings", systemImage: "gear") {
showSettings = true
}
.matchedTransitionSource(id: "settings", in: namespace)
}
}
.sheet(isPresented: $showSettings) {
SettingsView()
.navigationTransition(.zoom(sourceID: "settings", in: namespace))
.presentationDetents([.medium, .large])
}
}
}
}
Don't default to system fonts everywhere. Create typographic hierarchy:
// Display fonts for headers
Text("Dashboard")
.font(.largeTitle.bold())
.foregroundStyle(.primary)
// Secondary information
Text("Last updated 5 min ago")
.font(.subheadline)
.foregroundStyle(.secondary)
// Consider custom fonts for brand identity
Text("Premium")
.font(.custom("PlayfairDisplay-Bold", size: 32))
| Use Case | Options |
|---|---|
| Display | SF Pro Display, New York, custom serif |
| Body | SF Pro Text (system), custom sans |
| Technical | SF Mono, custom monospace |
| Editorial | New York, custom serif with character |
// Semantic colors that adapt
.foregroundStyle(.primary)
.foregroundStyle(.secondary)
.background(.background)
// Accent with purpose
.tint(.accentColor)
Don't distribute color evenly. Choose:
Dark mode often produces more distinctive results. Design dark, then adapt to light.
withAnimation(.bouncy) {
isExpanded.toggle()
}
// With parameters
withAnimation(.bouncy(duration: 0.5, extraBounce: 0.2)) {
state = newState
}
| Moment | Treatment |
|---|---|
| Button press | Scale to 0.95, spring back |
| State change | Morph, don't swap |
| List appear | Staggered fade-in |
| Sheet present | Zoom from source |
| Error | Shake with haptic |
Image(systemName: "checkmark.circle")
.symbolEffect(.drawOn, value: isComplete)
Image(systemName: "heart.fill")
.symbolEffect(.bounce, value: isFavorite)
import UIKit
// Impact feedback
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()
// Selection feedback
let selection = UISelectionFeedbackGenerator()
selection.selectionChanged()
// Success/error
let notification = UINotificationFeedbackGenerator()
notification.notificationOccurred(.success)
Glass automatically adapts to:
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation? {
reduceMotion ? nil : .bouncy
}
Before considering UI complete:
From 2025 Apple Design Award winners:
For official Apple documentation links, WWDC session IDs, and API quick reference tables, see reference.md.
Remember: The goal is an app worthy of an Apple Design Award—an app that feels genuinely designed, not generated. Every interface should have:
Don't settle for "working." Push for memorable.