liquid-glass-developer
Liquid Glass Developer (iOS 26)
Purpose
Context-aware routing to iOS 26 Liquid Glass implementation patterns. Proper use of GlassEffectContainer, glassEffect modifiers, morphing transitions, and interactive effects.
When Auto-Activated
- Working with glass effects or iOS 26 visual effects
- Keywords: glass, liquid glass, glassEffect, GlassEffectContainer, iOS 26, morphing, UIGlassEffect, UIVisualEffectView, cornerConfiguration, GlassContainerViewIOS26, GlassEffectViewIOS26
- Editing files with glass effect modifiers
- Implementing navigation panels, floating buttons, or translucent UI
🚨 CRITICAL RULES (NEVER VIOLATE)
- ALWAYS group glass elements in
GlassEffectContainerIOS26- Glass elements must be grouped for unified composition - ALWAYS use
glassEffectIDIOS26for morphing - Elements that appear/disappear need IDs for smooth transitions - Glass defines its shape - Use
glassEffect(in: Shape), no separateclipShape()needed - Glass is for navigation layer only - Never apply to content, only floating controls
- Use interactive glass for buttons - Buttons should use
.regular.interactive()for touch feedback
📋 Quick Reference
Available Utilities (View+iOS26.swift)
// Wrapper for GlassEffectContainer with iOS version check
GlassEffectContainerIOS26(spacing: 20) {
// Glass elements here
}
// Interactive glass effect (scaling/bounce on touch)
.glassEffectInteractiveIOS26(in: Circle())
.glassEffectInteractiveIOS26(in: .rect(cornerRadius: 16))
// Standard glass effect (no touch feedback)
.glassEffectIOS26(in: Circle())
// Morphing transition ID
.glassEffectIDIOS26("buttonId", in: glassNamespace)
// Circle glass button style (for Button views — handles full-frame hit testing)
.buttonStyleCircleGlassIOS26()
Complete Pattern Example
struct NavigationPanel: View {
@Namespace private var glassNamespace
@State private var isExpanded = false
var body: some View {
GlassEffectContainerIOS26(spacing: 20) {
HStack {
Button { } label: {
Image(systemName: "magnifyingglass")
.frame(width: 40, height: 40)
}
.glassEffectInteractiveIOS26(in: Circle())
.glassEffectIDIOS26("search", in: glassNamespace)
if isExpanded {
Button { } label: {
Image(systemName: "plus")
.frame(width: 40, height: 40)
}
.glassEffectInteractiveIOS26(in: Circle())
.glassEffectIDIOS26("add", in: glassNamespace)
}
}
}
.animation(.bouncy, value: isExpanded)
}
}
Glass Shapes
// Circular buttons
.glassEffectInteractiveIOS26(in: Circle())
// Rounded rectangle
.glassEffectInteractiveIOS26(in: .rect(cornerRadius: 16))
// Capsule
.glassEffectInteractiveIOS26(in: Capsule())
🔄 Morphing Transitions
For smooth state transitions between glass elements:
@Namespace private var glassNamespace
// Elements with same container + IDs morph smoothly
GlassEffectContainerIOS26 {
if editing {
plusButton
.glassEffectIDIOS26("leftButton", in: glassNamespace)
} else {
burgerButton
.glassEffectIDIOS26("leftButton", in: glassNamespace)
}
}
.animation(.bouncy, value: editing)
Key requirements:
- Elements in same
GlassEffectContainerIOS26 - Each element has
glassEffectIDIOS26with shared namespace - Wrap state changes with animation
⚠️ Common Mistakes
No Container Grouping
// ❌ WRONG - Individual glass effects
HStack {
button1.glassEffectIOS26(in: Circle())
button2.glassEffectIOS26(in: Circle())
}
// ✅ CORRECT - Grouped in container
GlassEffectContainerIOS26 {
HStack {
button1.glassEffectInteractiveIOS26(in: Circle())
button2.glassEffectInteractiveIOS26(in: Circle())
}
}
Redundant clipShape
// ❌ WRONG - clipShape before glass
.clipShape(Circle())
.glassEffectIOS26(in: Circle())
// ✅ CORRECT - Glass defines shape
.glassEffectInteractiveIOS26(in: Circle())
Missing Morphing IDs
// ❌ WRONG - Abrupt appear/disappear
if isVisible {
button.glassEffectInteractiveIOS26(in: Circle())
}
// ✅ CORRECT - Smooth morphing
if isVisible {
button
.glassEffectInteractiveIOS26(in: Circle())
.glassEffectIDIOS26("button", in: namespace)
}
Glass on Content
// ❌ WRONG - Glass on content
Text("Hello World")
.glassEffectIOS26(in: .rect(cornerRadius: 8))
// ✅ CORRECT - Glass only on floating controls
// Use standard backgrounds for content:
Text("Hello World")
.background(Color.Background.primary)
📚 iOS Version Handling
All utilities handle iOS version checks internally:
- iOS 26+: Native glass effects applied
- iOS < 26: Fallback to
Color.Background.navigationPanel + .ultraThinMaterial
// This works on all iOS versions
.glassEffectInteractiveIOS26(in: Circle())
// Equivalent to:
if #available(iOS 26.0, *) {
self.glassEffect(.regular.interactive(), in: Circle())
} else {
self
.background(Color.Background.navigationPanel)
.background(.ultraThinMaterial)
}
🔧 UIKit Implementation
Available Utilities (UIView+iOS26Glass.swift)
// Container for grouping glass elements (like GlassEffectContainerIOS26 in SwiftUI)
let container = GlassContainerViewIOS26(spacing: 12)
container.glassContentView.addSubview(yourContent)
// Individual glass effect view (always interactive)
let glassView = GlassEffectViewIOS26()
glassView.glassContentView.addSubview(yourButton)
// Glass button configuration
let config = UIButton.Configuration.glassIOS26()
let button = UIButton(configuration: config)
UIKit Pattern Example
final class NavigationBarView: UIView {
private let glassContainer = GlassContainerViewIOS26(spacing: 12)
private let buttonGlass = GlassEffectViewIOS26()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
private func setup() {
// Add container to view
addSubview(glassContainer) {
$0.pinToSuperview(insets: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16))
$0.height.equal(to: 44)
}
// Setup circular button with glass
buttonGlass.applyCircleShape(diameter: 44)
buttonGlass.layoutUsing.anchors {
$0.size(CGSize(width: 44, height: 44))
}
// Add button to glass content view (NOT directly to buttonGlass)
buttonGlass.glassContentView.addSubview(myButton) {
$0.center(in: buttonGlass.glassContentView)
}
// Add glass button to container's content view
glassContainer.glassContentView.addSubview(buttonGlass)
}
}
Shape Methods
// Circular buttons (44x44)
glassView.applyCircleShape(diameter: 44)
// Capsule/pill shape (e.g., for title views)
glassView.applyCapsuleShape(height: 44)
// iOS 26+: Uses cornerConfiguration = .capsule()
// iOS < 26: Uses layer.cornerRadius fallback
UIKit Critical Rules
-
Always add content to
glassContentView- Never add subviews directly to the glass view// ❌ WRONG glassView.addSubview(button) // ✅ CORRECT glassView.glassContentView.addSubview(button) -
Call shape methods once in setup - Not in
layoutSubviews(unless height changes dynamically)// ❌ WRONG - Called every layout pass override func layoutSubviews() { super.layoutSubviews() glassView.applyCapsuleShape(height: bounds.height) } // ✅ CORRECT - Called once with fixed height func setup() { glassView.applyCapsuleShape(height: 44) } -
GlassEffectViewIOS26 is always interactive - No property to set, touch feedback is built-in
-
Use glassIOS26() for text buttons
var config = UIButton.Configuration.glassIOS26() config.title = "Done" config.baseForegroundColor = .Control.accent100 let button = UIButton(configuration: config)
iOS Version Handling (UIKit)
// GlassEffectViewIOS26 handles version checks internally:
// iOS 26+: UIGlassEffect with cornerConfiguration
// iOS < 26: UIBlurEffect(style: .systemUltraThinMaterial) + Background.navigationPanel
// Example of internal implementation:
private func setupGlassEffect() {
if #available(iOS 26.0, *) {
let glassEffect = UIGlassEffect()
glassEffect.isInteractive = true
let effectView = UIVisualEffectView(effect: glassEffect)
addSubview(effectView)
glassEffectView = effectView
} else {
backgroundColor = .Background.navigationPanel
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterial))
addSubview(blurView)
}
}
📁 Key Files
| File | Purpose |
|---|---|
View+iOS26.swift |
SwiftUI glass effect utilities and wrappers |
UIView+iOS26Glass.swift |
UIKit glass effect utilities |
HomeBottomNavigationPanelView.swift |
Navigation panel with glass buttons |
ChatInput.swift |
Chat input with morphing burger/plus button |
ChatActionPanel.swift |
Action buttons with interactive glass |
EditorNavigationBarView.swift |
UIKit navigation bar with glass container |
EditorNavigationBarTitleView.swift |
UIKit title view with capsule glass |
🔗 External Resources
- Understanding GlassEffectContainer - DEV
- GlassEffectContainer - Apple Docs
- iOS 26 Liquid Glass Reference
- WWDC25: Build a SwiftUI app with the new design
✅ Implementation Checklist
SwiftUI
- Glass elements wrapped in
GlassEffectContainerIOS26 - Buttons use
glassEffectInteractiveIOS26(not justglassEffectIOS26) - State-dependent elements have
glassEffectIDIOS26for morphing - No redundant
clipShape()before glass effects - Glass only on navigation/floating controls, not content
- Animation wrapper for state changes (
withAnimation(.bouncy)or.animation())
UIKit
- Glass elements wrapped in
GlassContainerViewIOS26 - Content added to
glassContentView(not directly to glass view) - Shape methods called once in setup (not
layoutSubviews) - Text buttons use
UIButton.Configuration.glassIOS26() - Circular buttons use
applyCircleShape(diameter:) - Pill/capsule shapes use
applyCapsuleShape(height:)
Testing
- Tested on iOS 26 simulator for glass appearance
- Tested on iOS 18 simulator for fallback behavior
🔗 Related Skills
- design-system-developer → Icons and colors used in glass buttons
- ios-dev-guidelines → SwiftUI patterns and view modifiers
Navigation: This skill covers iOS 26 Liquid Glass patterns. For implementation details, see View+iOS26.swift.
More from anyproto/anytype-swift
tests-developer
Smart router to testing patterns and practices. Use when writing unit tests, creating mocks, testing edge cases, or working with Swift Testing and XCTest frameworks.
2localization-developer
Context-aware routing to the Anytype iOS localization system. Use when working with .xcstrings files, Loc constants, hardcoded strings, or user-facing text.
2ios-dev-guidelines
Context-aware routing to Swift/iOS development patterns, architecture, and best practices. Use when working with .swift files, ViewModels, Coordinators, refactoring, or discussing Swift/SwiftUI patterns.
2swiftui-performance-developer
Audit and improve SwiftUI runtime performance through code review and Instruments guidance. Use for diagnosing slow rendering, janky scrolling, excessive view updates, or layout thrash in SwiftUI apps.
2swift-concurrency-developer
Expert guidance on Swift concurrency using the Office Building mental model. Use when working with actors, isolation, Sendable, TaskGroups, or fixing concurrency warnings and data race issues.
2swiftui-patterns-developer
SwiftUI view structure, composition, and best practices. Use when refactoring SwiftUI views, organizing view files, or extracting subviews.
2