buildanything 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +55 -0
- package/README.md +71 -61
- package/agents/ios-app-review-guardian.md +49 -0
- package/agents/ios-foundation-models-specialist.md +46 -0
- package/agents/ios-storekit-specialist.md +52 -0
- package/agents/ios-swift-architect.md +102 -0
- package/agents/ios-swift-search.md +130 -0
- package/agents/ios-swift-ui-design.md +104 -0
- package/commands/build.md +80 -176
- package/commands/fix.md +65 -0
- package/commands/setup.md +73 -0
- package/commands/ux-review.md +63 -0
- package/commands/verify.md +72 -0
- package/hooks/session-start +18 -1
- package/package.json +5 -2
- package/protocols/brainstorm.md +99 -0
- package/protocols/build-fix.md +52 -0
- package/protocols/cleanup.md +54 -0
- package/protocols/design.md +269 -0
- package/protocols/eval-harness.md +61 -0
- package/protocols/fake-data-detector.md +64 -0
- package/protocols/ios-context.md +235 -0
- package/protocols/ios-frameworks-map.md +323 -0
- package/protocols/ios-phase-branches.md +162 -0
- package/protocols/ios-preflight.md +27 -0
- package/protocols/metric-loop.md +93 -0
- package/protocols/planning.md +87 -0
- package/protocols/smoke-test.md +110 -0
- package/protocols/verify.md +67 -0
- package/protocols/web-phase-branches.md +201 -0
- package/skills/ios/_VENDORED.md +60 -0
- package/skills/ios/activitykit/LICENSE +131 -0
- package/skills/ios/activitykit/SKILL.md +505 -0
- package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
- package/skills/ios/app-intents/LICENSE +131 -0
- package/skills/ios/app-intents/SKILL.md +494 -0
- package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
- package/skills/ios/apple-on-device-ai/LICENSE +131 -0
- package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
- package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
- package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
- package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
- package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
- package/skills/ios/ios-26-platform/SKILL.md +53 -0
- package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
- package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
- package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
- package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
- package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
- package/skills/ios/ios-bootstrap/SKILL.md +98 -0
- package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
- package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
- package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
- package/skills/ios/ios-debugger-agent/LICENSE +21 -0
- package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
- package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
- package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
- package/skills/ios/ios-hig/SKILL.md +41 -0
- package/skills/ios/ios-hig/references/accessibility.md +81 -0
- package/skills/ios/ios-hig/references/content.md +142 -0
- package/skills/ios/ios-hig/references/feedback.md +123 -0
- package/skills/ios/ios-hig/references/interaction.md +199 -0
- package/skills/ios/ios-hig/references/performance-platform.md +129 -0
- package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
- package/skills/ios/ios-hig/references/visual-design.md +84 -0
- package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
- package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
- package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
- package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
- package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
- package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
- package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
- package/skills/ios/swift-accessibility/LICENSE +21 -0
- package/skills/ios/swift-accessibility/SKILL.md +371 -0
- package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
- package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
- package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
- package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
- package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
- package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
- package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
- package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
- package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
- package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
- package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
- package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
- package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
- package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
- package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
- package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
- package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
- package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
- package/skills/ios/swift-concurrency/LICENSE +21 -0
- package/skills/ios/swift-concurrency/SKILL.md +171 -0
- package/skills/ios/swift-concurrency/references/_index.md +50 -0
- package/skills/ios/swift-concurrency/references/actors.md +660 -0
- package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
- package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
- package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
- package/skills/ios/swift-concurrency/references/core-data.md +560 -0
- package/skills/ios/swift-concurrency/references/glossary.md +135 -0
- package/skills/ios/swift-concurrency/references/linting.md +155 -0
- package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
- package/skills/ios/swift-concurrency/references/migration.md +1104 -0
- package/skills/ios/swift-concurrency/references/performance.md +593 -0
- package/skills/ios/swift-concurrency/references/sendable.md +598 -0
- package/skills/ios/swift-concurrency/references/tasks.md +636 -0
- package/skills/ios/swift-concurrency/references/testing.md +592 -0
- package/skills/ios/swift-concurrency/references/threading.md +495 -0
- package/skills/ios/swift-security-expert/LICENSE +21 -0
- package/skills/ios/swift-security-expert/SKILL.md +470 -0
- package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
- package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
- package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
- package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
- package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
- package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
- package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
- package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
- package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
- package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
- package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
- package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
- package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
- package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
- package/skills/ios/swift-testing-expert/LICENSE +21 -0
- package/skills/ios/swift-testing-expert/SKILL.md +79 -0
- package/skills/ios/swift-testing-expert/references/_index.md +12 -0
- package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
- package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
- package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
- package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
- package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
- package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
- package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
- package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
- package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
- package/skills/ios/swiftdata-pro/LICENSE +21 -0
- package/skills/ios/swiftdata-pro/SKILL.md +102 -0
- package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
- package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
- package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
- package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
- package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
- package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
- package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
- package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
- package/skills/ios/swiftui-design-principles/LICENSE +21 -0
- package/skills/ios/swiftui-design-principles/README.md +41 -0
- package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
- package/skills/ios/swiftui-design-principles/metadata.json +10 -0
- package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
- package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
- package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
- package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
- package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
- package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
- package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/skills/ios/swiftui-pro/LICENSE +21 -0
- package/skills/ios/swiftui-pro/SKILL.md +108 -0
- package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
- package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
- package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
- package/skills/ios/swiftui-pro/references/api.md +39 -0
- package/skills/ios/swiftui-pro/references/data.md +43 -0
- package/skills/ios/swiftui-pro/references/design.md +31 -0
- package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
- package/skills/ios/swiftui-pro/references/navigation.md +14 -0
- package/skills/ios/swiftui-pro/references/performance.md +46 -0
- package/skills/ios/swiftui-pro/references/swift.md +56 -0
- package/skills/ios/swiftui-pro/references/views.md +35 -0
- package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
- package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
- package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
- package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
- package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
- package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
- package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
- package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
- package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
- package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
- package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
- package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
- package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
- package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
- package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
- package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
- package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
- package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
- package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
- package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/skills/ios/widgetkit/LICENSE +131 -0
- package/skills/ios/widgetkit/SKILL.md +502 -0
- package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Backward Compatibility
|
|
2
|
+
|
|
3
|
+
**iOS 17/18 + iOS 26**
|
|
4
|
+
|
|
5
|
+
## UIDesignRequiresCompatibility Key
|
|
6
|
+
|
|
7
|
+
### Opt Out of Liquid Glass (Temporarily)
|
|
8
|
+
```xml
|
|
9
|
+
<!-- Info.plist -->
|
|
10
|
+
<key>UIDesignRequiresCompatibility</key>
|
|
11
|
+
<true/>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**Effect**:
|
|
15
|
+
- App built with iOS 26 SDK
|
|
16
|
+
- Appearance matches iOS 18 and earlier
|
|
17
|
+
- Liquid Glass effects disabled
|
|
18
|
+
- Previous blur/material styles used
|
|
19
|
+
|
|
20
|
+
### Migration Strategy
|
|
21
|
+
1. Ship with `UIDesignRequiresCompatibility` enabled
|
|
22
|
+
2. Audit interface changes in separate build
|
|
23
|
+
3. Update interface incrementally
|
|
24
|
+
4. Remove key when ready for Liquid Glass
|
|
25
|
+
|
|
26
|
+
## @available Patterns
|
|
27
|
+
|
|
28
|
+
### Basic Check
|
|
29
|
+
```swift
|
|
30
|
+
if #available(iOS 26, *) {
|
|
31
|
+
content
|
|
32
|
+
.glassEffect()
|
|
33
|
+
} else {
|
|
34
|
+
content
|
|
35
|
+
.background(.ultraThinMaterial)
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### View Modifier Pattern
|
|
40
|
+
```swift
|
|
41
|
+
extension View {
|
|
42
|
+
@ViewBuilder
|
|
43
|
+
func adaptiveGlass() -> some View {
|
|
44
|
+
if #available(iOS 26, *) {
|
|
45
|
+
self.glassEffect()
|
|
46
|
+
} else {
|
|
47
|
+
self.background(.regularMaterial)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Usage
|
|
53
|
+
Button("Action") { }
|
|
54
|
+
.adaptiveGlass()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Toolbar Spacer Fallback
|
|
58
|
+
```swift
|
|
59
|
+
extension View {
|
|
60
|
+
@ViewBuilder
|
|
61
|
+
func adaptiveToolbar() -> some View {
|
|
62
|
+
if #available(iOS 26, *) {
|
|
63
|
+
self.toolbar {
|
|
64
|
+
ToolbarItemGroup(placement: .topBarTrailing) {
|
|
65
|
+
Button("Up") { }
|
|
66
|
+
Button("Down") { }
|
|
67
|
+
Spacer(.fixed) // iOS 26 feature
|
|
68
|
+
Button("Settings") { }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
self.toolbar {
|
|
73
|
+
ToolbarItem(placement: .topBarTrailing) {
|
|
74
|
+
Button("Up") { }
|
|
75
|
+
}
|
|
76
|
+
ToolbarItem(placement: .topBarTrailing) {
|
|
77
|
+
Button("Down") { }
|
|
78
|
+
}
|
|
79
|
+
ToolbarItem(placement: .topBarTrailing) {
|
|
80
|
+
Button("Settings") { }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## WebView Fallback
|
|
89
|
+
|
|
90
|
+
```swift
|
|
91
|
+
struct ArticleView: View {
|
|
92
|
+
let url: URL
|
|
93
|
+
|
|
94
|
+
var body: some View {
|
|
95
|
+
if #available(iOS 26, *) {
|
|
96
|
+
WebView(url: url)
|
|
97
|
+
} else {
|
|
98
|
+
WebViewRepresentable(url: url) // UIViewRepresentable wrapper
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// iOS 17/18 fallback
|
|
104
|
+
struct WebViewRepresentable: UIViewRepresentable {
|
|
105
|
+
let url: URL
|
|
106
|
+
|
|
107
|
+
func makeUIView(context: Context) -> WKWebView {
|
|
108
|
+
WKWebView()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func updateUIView(_ webView: WKWebView, context: Context) {
|
|
112
|
+
webView.load(URLRequest(url: url))
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## @Animatable Fallback
|
|
118
|
+
|
|
119
|
+
```swift
|
|
120
|
+
#if swift(>=6.0)
|
|
121
|
+
@Animatable
|
|
122
|
+
struct ModernShape: Shape {
|
|
123
|
+
var progress: Double
|
|
124
|
+
|
|
125
|
+
@AnimatableIgnored
|
|
126
|
+
var style: ShapeStyle
|
|
127
|
+
}
|
|
128
|
+
#else
|
|
129
|
+
struct LegacyShape: Shape {
|
|
130
|
+
var progress: Double
|
|
131
|
+
|
|
132
|
+
var animatableData: Double {
|
|
133
|
+
get { progress }
|
|
134
|
+
set { progress = newValue }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
#endif
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Search Tab Role Fallback
|
|
141
|
+
|
|
142
|
+
```swift
|
|
143
|
+
TabView {
|
|
144
|
+
if #available(iOS 26, *) {
|
|
145
|
+
SearchView()
|
|
146
|
+
.tabItem { Label("Search", systemImage: "magnifyingglass") }
|
|
147
|
+
.tabRole(.search)
|
|
148
|
+
} else {
|
|
149
|
+
SearchView()
|
|
150
|
+
.tabItem { Label("Search", systemImage: "magnifyingglass") }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## AttributedString TextEditor
|
|
156
|
+
|
|
157
|
+
```swift
|
|
158
|
+
struct CommentEditor: View {
|
|
159
|
+
@State private var richText = AttributedString("Comment")
|
|
160
|
+
@State private var plainText = "Comment"
|
|
161
|
+
|
|
162
|
+
var body: some View {
|
|
163
|
+
if #available(iOS 26, *) {
|
|
164
|
+
TextEditor(text: $richText) // Rich text support
|
|
165
|
+
} else {
|
|
166
|
+
TextEditor(text: $plainText) // Plain text only
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Migration from Previous Materials
|
|
173
|
+
|
|
174
|
+
### From UIBlurEffect
|
|
175
|
+
```swift
|
|
176
|
+
// Before (UIKit)
|
|
177
|
+
let blurEffect = UIBlurEffect(style: .systemMaterial)
|
|
178
|
+
let blurView = UIVisualEffectView(effect: blurEffect)
|
|
179
|
+
|
|
180
|
+
// After (SwiftUI with fallback)
|
|
181
|
+
extension View {
|
|
182
|
+
@ViewBuilder
|
|
183
|
+
func adaptiveMaterial() -> some View {
|
|
184
|
+
if #available(iOS 26, *) {
|
|
185
|
+
self.glassEffect()
|
|
186
|
+
} else {
|
|
187
|
+
self.background(.regularMaterial)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### From Custom Materials
|
|
194
|
+
Keep custom materials when:
|
|
195
|
+
- Backward compatibility with iOS < 26 required
|
|
196
|
+
- Specific artistic effect not achievable with glass
|
|
197
|
+
- Non-standard UI paradigm
|
|
198
|
+
|
|
199
|
+
## Testing Checklist
|
|
200
|
+
|
|
201
|
+
### iOS 26 Tests
|
|
202
|
+
- [ ] Liquid Glass appearance correct
|
|
203
|
+
- [ ] Scroll edge effects working
|
|
204
|
+
- [ ] Toolbar grouping renders properly
|
|
205
|
+
- [ ] Search placement is platform-appropriate
|
|
206
|
+
- [ ] Accessibility settings respected
|
|
207
|
+
|
|
208
|
+
### iOS 17/18 Tests
|
|
209
|
+
- [ ] Fallback materials render correctly
|
|
210
|
+
- [ ] No runtime crashes from @available checks
|
|
211
|
+
- [ ] Functionality preserved without glass
|
|
212
|
+
- [ ] Layout doesn't break
|
|
213
|
+
|
|
214
|
+
## Deprecated APIs
|
|
215
|
+
|
|
216
|
+
### iPadOS 26
|
|
217
|
+
```xml
|
|
218
|
+
<!-- Remove entirely — deprecated in iPadOS 26 -->
|
|
219
|
+
<key>UIRequiresFullscreen</key>
|
|
220
|
+
```
|
|
221
|
+
Apps must support resizable windows on iPad.
|
|
222
|
+
|
|
223
|
+
### SwiftUI Updates
|
|
224
|
+
```swift
|
|
225
|
+
// Old (deprecated)
|
|
226
|
+
.onChange(of: value, perform: { newValue in })
|
|
227
|
+
|
|
228
|
+
// New (iOS 17+)
|
|
229
|
+
.onChange(of: value) { oldValue, newValue in }
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Performance Considerations
|
|
233
|
+
|
|
234
|
+
When supporting multiple iOS versions:
|
|
235
|
+
- Use `@available` checks at view level, not inside body
|
|
236
|
+
- Prefer conditional view modifiers over entire view branches
|
|
237
|
+
- Test performance on oldest supported version
|
|
238
|
+
- Profile with Instruments on both old and new iOS
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Liquid Glass Design System
|
|
2
|
+
|
|
3
|
+
**iOS 26+, iPadOS 26+, macOS Tahoe+, visionOS 3+**
|
|
4
|
+
|
|
5
|
+
## What is Liquid Glass?
|
|
6
|
+
|
|
7
|
+
Apple's next-generation material that dynamically bends light (lensing) rather than scattering it. Unlike blur effects, Liquid Glass:
|
|
8
|
+
- Moves organically like lightweight liquid
|
|
9
|
+
- Adapts automatically to size, environment, and light/dark modes
|
|
10
|
+
- Provides separation through instinctive visual cues
|
|
11
|
+
|
|
12
|
+
## Visual Properties
|
|
13
|
+
|
|
14
|
+
### Lensing (Primary Characteristic)
|
|
15
|
+
```swift
|
|
16
|
+
// Glass warps and bends light in real-time
|
|
17
|
+
Text("Hello")
|
|
18
|
+
.glassEffect() // Lensing effect, not blur
|
|
19
|
+
```
|
|
20
|
+
- Concentrates and shapes light dynamically
|
|
21
|
+
- Elements feel ultra-lightweight yet distinguishable
|
|
22
|
+
- Materializes in/out by modulating light bending (not fading)
|
|
23
|
+
|
|
24
|
+
### Motion & Fluidity
|
|
25
|
+
- Instant flex and energize on interaction
|
|
26
|
+
- Gel-like flexibility for transient UI
|
|
27
|
+
- Dynamic morphing between app states
|
|
28
|
+
- Lightweight transitions (menus pop open in-line)
|
|
29
|
+
|
|
30
|
+
### Adaptive Behavior
|
|
31
|
+
- Shadows increase when text scrolls underneath
|
|
32
|
+
- Independently switches light/dark per element
|
|
33
|
+
- Larger elements (menus, sidebars) simulate thicker material
|
|
34
|
+
- Ambient environment subtly spills onto surface
|
|
35
|
+
|
|
36
|
+
## Variants: Regular vs Clear
|
|
37
|
+
|
|
38
|
+
**CRITICAL**: Never mix Regular and Clear in the same interface.
|
|
39
|
+
|
|
40
|
+
### Regular Variant (Default - Use 95% of Time)
|
|
41
|
+
```swift
|
|
42
|
+
// Regular is the default — most versatile
|
|
43
|
+
NavigationView {
|
|
44
|
+
Content()
|
|
45
|
+
}
|
|
46
|
+
.glassEffect() // Full adaptive effects, auto-legibility
|
|
47
|
+
|
|
48
|
+
// With custom shape
|
|
49
|
+
Button("Tap Me") { }
|
|
50
|
+
.glassEffect(in: RoundedRectangle(cornerRadius: 12))
|
|
51
|
+
```
|
|
52
|
+
- Works in any size, over any content
|
|
53
|
+
- Provides legibility regardless of context
|
|
54
|
+
- Anything can be placed on top
|
|
55
|
+
|
|
56
|
+
### Clear Variant (Special Cases Only)
|
|
57
|
+
```swift
|
|
58
|
+
// Use ONLY when ALL THREE conditions are met:
|
|
59
|
+
// 1. Over media-rich content
|
|
60
|
+
// 2. Dimming layer acceptable
|
|
61
|
+
// 3. Content above is bold and bright
|
|
62
|
+
|
|
63
|
+
ZStack {
|
|
64
|
+
VideoPlayer(player: player)
|
|
65
|
+
.overlay(.black.opacity(0.3)) // Required dimming layer
|
|
66
|
+
|
|
67
|
+
PlayButton()
|
|
68
|
+
.glassEffect(.clear) // Clear variant
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**WARNING**: Clear without meeting all three conditions = poor legibility.
|
|
73
|
+
|
|
74
|
+
## Layer Architecture
|
|
75
|
+
|
|
76
|
+
### Navigation Layer (Use Glass Here)
|
|
77
|
+
```swift
|
|
78
|
+
// Correct — glass on navigation elements
|
|
79
|
+
.toolbar {
|
|
80
|
+
ToolbarItem {
|
|
81
|
+
Button("Add") { }
|
|
82
|
+
.glassEffect()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Content Layer (No Glass)
|
|
88
|
+
```swift
|
|
89
|
+
// Wrong — don't apply glass to content
|
|
90
|
+
List(items) { item in
|
|
91
|
+
ItemRow(item)
|
|
92
|
+
.glassEffect() // Never do this
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## DO: Best Practices
|
|
97
|
+
|
|
98
|
+
```swift
|
|
99
|
+
// Reserve glass for navigation layer
|
|
100
|
+
TabView { ... } // Gets glass automatically
|
|
101
|
+
|
|
102
|
+
// Use fills for elements ON TOP of glass
|
|
103
|
+
ZStack {
|
|
104
|
+
NavigationBar()
|
|
105
|
+
.glassEffect()
|
|
106
|
+
|
|
107
|
+
FloatingButton()
|
|
108
|
+
.foregroundStyle(.primary) // Fills, not glass
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Use adaptive tinting for primary actions
|
|
112
|
+
Button("View Bag") { }
|
|
113
|
+
.tint(.red)
|
|
114
|
+
.glassEffect()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## DON'T: Common Mistakes
|
|
118
|
+
|
|
119
|
+
```swift
|
|
120
|
+
// Don't stack glass on glass
|
|
121
|
+
ZStack {
|
|
122
|
+
Toolbar().glassEffect()
|
|
123
|
+
Button().glassEffect() // Wrong
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Don't use solid fills on glass
|
|
127
|
+
Button("Action") { }
|
|
128
|
+
.background(.red) // Breaks glass character
|
|
129
|
+
.glassEffect()
|
|
130
|
+
|
|
131
|
+
// Don't tint everything
|
|
132
|
+
VStack {
|
|
133
|
+
Button("A").tint(.blue).glassEffect()
|
|
134
|
+
Button("B").tint(.green).glassEffect() // No hierarchy
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Scroll Edge Effects
|
|
139
|
+
|
|
140
|
+
```swift
|
|
141
|
+
ScrollView {
|
|
142
|
+
Content()
|
|
143
|
+
}
|
|
144
|
+
.scrollEdgeEffectStyle(.hard, for: .top) // Uniform effect
|
|
145
|
+
|
|
146
|
+
// .soft for gradual fade
|
|
147
|
+
// .hard for pinned accessories
|
|
148
|
+
// .automatic for system default
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Accessibility
|
|
152
|
+
|
|
153
|
+
All features automatic when using glass:
|
|
154
|
+
- **Reduced Transparency**: Makes glass frostier
|
|
155
|
+
- **Increased Contrast**: Black/white with contrasting border
|
|
156
|
+
- **Reduced Motion**: Decreases effect intensity
|
|
157
|
+
|
|
158
|
+
## GlassEffectContainer
|
|
159
|
+
|
|
160
|
+
Group multiple glass effects for performance and morphing animations:
|
|
161
|
+
|
|
162
|
+
```swift
|
|
163
|
+
GlassEffectContainer(spacing: 8) {
|
|
164
|
+
HStack(spacing: 8) {
|
|
165
|
+
Button { } label: { Image(systemName: "plus") }
|
|
166
|
+
.glassEffect()
|
|
167
|
+
.glassEffectID("add", in: namespace)
|
|
168
|
+
|
|
169
|
+
Button { } label: { Image(systemName: "share") }
|
|
170
|
+
.glassEffect()
|
|
171
|
+
.glassEffectID("share", in: namespace)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- Groups glass effects for better rendering performance
|
|
177
|
+
- Enables morphing transitions between elements
|
|
178
|
+
- Use `spacing` parameter to control when effects blend together
|
|
179
|
+
|
|
180
|
+
## Morphing with glassEffectID
|
|
181
|
+
|
|
182
|
+
Use `@Namespace` and `.glassEffectID()` for smooth morphing transitions:
|
|
183
|
+
|
|
184
|
+
```swift
|
|
185
|
+
@Namespace var namespace
|
|
186
|
+
|
|
187
|
+
// Elements with same ID morph into each other during transitions
|
|
188
|
+
if isExpanded {
|
|
189
|
+
ExpandedView()
|
|
190
|
+
.glassEffect()
|
|
191
|
+
.glassEffectID("panel", in: namespace)
|
|
192
|
+
} else {
|
|
193
|
+
CollapsedView()
|
|
194
|
+
.glassEffect()
|
|
195
|
+
.glassEffectID("panel", in: namespace)
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Interactive Glass
|
|
200
|
+
|
|
201
|
+
Add touch response with `.interactive()` chained on the glass variant:
|
|
202
|
+
|
|
203
|
+
```swift
|
|
204
|
+
// Correct - chain .interactive() on the variant
|
|
205
|
+
Button("Tap") { }
|
|
206
|
+
.glassEffect(.regular.interactive())
|
|
207
|
+
|
|
208
|
+
// With tint
|
|
209
|
+
Button("Tap") { }
|
|
210
|
+
.glassEffect(.regular.interactive().tint(.blue))
|
|
211
|
+
|
|
212
|
+
// With custom shape
|
|
213
|
+
Button("Tap") { }
|
|
214
|
+
.glassEffect(.regular.interactive(), in: .rect(cornerRadius: 12))
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Caution**: Avoid `.interactive()` on draggable rows - it can interfere with drag gestures.
|
|
218
|
+
|
|
219
|
+
## Known Limitations
|
|
220
|
+
|
|
221
|
+
**Drag previews**: Glass effects don't render correctly in drag previews. When using `.contentShape(.dragPreview, ...)`, the glass material won't appear during the lift animation. Use simple shapes for drag previews:
|
|
222
|
+
|
|
223
|
+
```swift
|
|
224
|
+
// Glass won't show in drag preview - this is expected
|
|
225
|
+
MyGlassCard()
|
|
226
|
+
.glassEffect()
|
|
227
|
+
.contentShape(.dragPreview, RoundedRectangle(cornerRadius: 12))
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## API Reference
|
|
231
|
+
|
|
232
|
+
```swift
|
|
233
|
+
// Basic glass effect
|
|
234
|
+
func glassEffect<S: Shape>(
|
|
235
|
+
_ glass: Glass = .regular,
|
|
236
|
+
in shape: S = Capsule()
|
|
237
|
+
) -> some View
|
|
238
|
+
|
|
239
|
+
// Glass variant modifiers (chainable)
|
|
240
|
+
Glass.regular.interactive() // Adds touch response
|
|
241
|
+
Glass.regular.tint(.color) // Adds color tint
|
|
242
|
+
Glass.regular.interactive().tint(.color) // Both
|
|
243
|
+
|
|
244
|
+
// Morphing support
|
|
245
|
+
func glassEffectID<ID: Hashable>(_ id: ID, in namespace: Namespace.ID) -> some View
|
|
246
|
+
|
|
247
|
+
// Container for multiple effects
|
|
248
|
+
GlassEffectContainer(spacing: CGFloat) { content }
|
|
249
|
+
|
|
250
|
+
// For custom views (reflects surrounding content)
|
|
251
|
+
func glassBackgroundEffect() -> some View
|
|
252
|
+
|
|
253
|
+
// Scroll edge styling
|
|
254
|
+
func scrollEdgeEffectStyle(_ style: ScrollEdgeStyle, for edges: Edge.Set) -> some View
|
|
255
|
+
```
|