coco-research/axiom-liquid-glass
Apple Liquid Glass design system — comprehensive design philosophy, implementation guide, and technical API reference from WWDC 2025. Covers design principles (iOS-native glass hierarchy, restraint over spectacle), implementation patterns (Regular vs Clear variants, SwiftUI glassEffect API, scroll edge effects, tinting), platform adaptation (iOS 26+, iPadOS 26+, macOS Tahoe+, visionOS 3+), accessibility, performance, testing, design review frameworks, and iOS-native UI redesign guidance.
npx skills add https://github.com/coco-research/coco --skill axiom-liquid-glass
Avoid trendy glassmorphism gimmicks. Glass effects should appear only where they improve clarity and depth. Every screen should feel like it belongs in a first-party Apple app.
Liquid Glass is Apple's next-generation material design system introduced at WWDC 2025. It represents a significant evolution from previous materials (Aqua, iOS 7 blurs, Dynamic Island) by creating a new digital meta-material that:
Use glass materials to express depth and context:
| Material | Use For | Visual Weight |
|----------|---------|---------------|
| Ultra-thin | Subtle overlays, toolbars, floating controls | Lightest |
| Regular | Cards needing gentle separation | Medium |
| Thick | Bottom sheets, modals, areas requiring strong readability | Heaviest |
Rules:
Liquid Glass defines itself through lensing — the warping and bending of light that communicates presence, motion, and form. Unlike previous materials that scattered light, Liquid Glass uses instinctive visual cues from the natural world.
Liquid Glass continuously adapts without fixed light/dark appearance:
glassEffect Modifier// Basic usage - applies glass within capsule shape
Text("Hello")
.glassEffect()
// Custom shape
Text("Hello")
.glassEffect(in: RoundedRectangle(cornerRadius: 12))
// Interactive elements (iOS)
Button("Tap Me") { }
.glassEffect()
.interactive()
Automatic Adoption: Simply recompiling with Xcode 26 brings Liquid Glass to standard controls automatically.
CRITICAL DECISION: Never mix Regular and Clear in the same interface.
When to use: Navigation bars, tab bars, toolbars, buttons, menus, sidebars
NavigationView {
// Content
}
.glassEffect() // Uses Regular variant by default
Use ONLY when ALL three conditions are met:
ZStack {
MediaRichBackground()
.overlay(.black.opacity(0.3)) // Dimming layer
BoldBrightControl()
.glassEffect(.clear)
}
WARNING: Using Clear without meeting all three conditions results in poor legibility.
[Content Layer — No Glass]
|
[Navigation Layer — Liquid Glass]
- Tab bars, Navigation bars, Toolbars, Floating controls
// WRONG
List(items) { item in
Text(item.name)
}
.glassEffect() // Competes with navigation, muddy hierarchy
// WRONG
ZStack {
NavigationBar().glassEffect()
FloatingButton().glassEffect() // Glass on glass
}
// CORRECT
ZStack {
NavigationBar().glassEffect()
FloatingButton()
.foregroundStyle(.primary) // Use fills, transparency, vibrancy
}
Reposition or scale content to maintain separation. Intersections are acceptable during scrolling/transitions.
Button("Primary Action") { }
.tint(.red)
.glassEffect()
// WRONG - Solid fill breaks glass character
Button("Action") {}
.background(.red) // Opaque
// CORRECT - Transparent, grounded
Button("Action") {}
.tint(.red)
.glassEffect()
Work in concert with Liquid Glass to maintain separation with scrolling content.
Use when pinned accessory views exist:
ScrollView { }
.scrollEdgeEffect(.hard)
Liquid Glass offers accessibility features that modify material without sacrificing its magic:
| Feature | Effect | Developer Action |
|---------|--------|-----------------|
| Reduced Transparency | Makes glass frostier, obscures more | Automatic |
| Increased Contrast | Elements predominantly black/white with contrasting border | Automatic |
| Reduced Motion | Decreases intensity, disables elastic properties | Automatic |
No developer action required — all features apply automatically when using Liquid Glass.
// WRONG - Deep nesting
ZStack {
GlassContainer1().glassEffect()
ZStack {
GlassContainer2().glassEffect()
}
}
// CORRECT - Flat hierarchy
VStack {
GlassContainer1().glassEffect()
GlassContainer2().glassEffect()
}
func testLiquidGlassAppearance() {
let app = XCUIApplication()
app.launch()
// Test light mode
XCTContext.runActivity(named: "Light Mode Glass") { _ in
let screenshot = app.screenshot()
}
// Test dark mode
app.launchArguments = ["-UIUserInterfaceStyle", "dark"]
app.launch()
XCTContext.runActivity(named: "Dark Mode Glass") { _ in
let screenshot = app.screenshot()
}
}
func testLiquidGlassAccessibility() {
app.launchArguments += [
"-UIAccessibilityIsReduceTransparencyEnabled", "1",
"-UIAccessibilityButtonShapesEnabled", "1",
"-UIAccessibilityIsReduceMotionEnabled", "1"
]
XCTAssertTrue(glassElement.exists)
XCTAssertTrue(glassElement.isHittable)
}
If you hear ANY of these, STOP and reference the skill:
Step 1: Show the Framework
"Let me show you Apple's guidance on Clear variant.
It requires THREE conditions:
1. Media-rich content background
2. Dimming layer for legibility
3. Bold, bright controls on top
Let me show which screens meet all three..."
Step 2: Demonstrate the Risk
Open the app on a device. Show Clear variant in low-contrast scenario (unreadable) vs Regular (legible).
Step 3: Offer Compromise
"Clear works beautifully in these hero sections where all three conditions apply.
Regular handles everything else with automatic legibility. Best of both worlds."
Step 4: Document the Decision
If overruled, send written documentation of the decision and monitoring plan.
glassEffect(in:isInteractive:)func glassEffect<S: Shape>(
in shape: S = Capsule(),
isInteractive: Bool = false
) -> some View
glassEffect(_:in:isInteractive:)func glassEffect<S: Shape>(
_ variant: GlassVariant, // .regular or .clear
in shape: S = Capsule(),
isInteractive: Bool = false
) -> some View
scrollEdgeEffect(_:)func scrollEdgeEffect(_ style: ScrollEdgeStyle) -> some View
// styles: .automatic, .soft, .hard
scrollEdgeEffectStyle(_:for:) (NEW in iOS 26)func scrollEdgeEffectStyle(_ style: ScrollEdgeStyle, for edges: Edge.Set) -> some View
glassBackgroundEffect() (NEW in iOS 26)Apply glass effect to custom views for reflecting surrounding content.
CustomPhotoGrid()
.glassBackgroundEffect()
GlassEffectContainer (NEW in iOS 26)Container for combining multiple Liquid Glass effects with optimized rendering.
GlassEffectContainer {
HStack {
Button("Action 1") { }.glassEffect()
Button("Action 2") { }.glassEffect()
}
}
Benefits: Optimizes rendering, fluid morphing between glass shapes, reduced compositor overhead.
Spacer(.fixed) in ToolbarsSeparates toolbar button groups with fixed spacing.
.buttonStyle(.borderedProminent) + .tint() in ToolbarsMakes toolbar items prominent with Liquid Glass tinting.
.searchable()).tabRole(.search) — morphs into search field.tabBarMinimizationBehavior(.onScrollDown)enum GlassVariant {
case regular // Default - full adaptive behavior
case clear // More transparent, no adaptation
}
enum ScrollEdgeStyle {
case automatic // System determines
case soft // Gradual fade
case hard // Uniform across toolbar height
}
Add to Info.plist to maintain iOS 18 appearance while building with iOS 26 SDK:
<key>UIDesignRequiresCompatibility</key>
<true/>
Migration strategy:
For each redesigned screen, provide:
WWDC: 2025-219, 2025-323, 2025-256
Docs: /technologyoverviews/adopting-liquid-glass, /swiftui/landmarks-building-an-app-with-liquid-glass, /swiftui/applying-liquid-glass-to-custom-views
Related Skills: axiom-liquid-glass-ref, swiftui-liquid-glass
Platforms: iOS 26+, iPadOS 26+, macOS Tahoe, visionOS 3
Xcode: 26+
Take coco-research/axiom-liquid-glass from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.