@mmerterden/multi-agent-pipeline 20.17.1 → 20.17.2

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/docs/facts.json +6 -6
  3. package/install/catalog-history.json +1 -1
  4. package/manifest.json +75 -37
  5. package/package.json +1 -1
  6. package/pipeline/skills/.skill-manifest.json +33 -13
  7. package/pipeline/skills/.skills-index.json +66 -11
  8. package/pipeline/skills/shared/README.md +18 -13
  9. package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +3 -1
  10. package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +2 -1
  11. package/pipeline/skills/shared/external/hig-app-icons/SKILL.md +159 -0
  12. package/pipeline/skills/shared/external/hig-app-icons/evals/evals.json +48 -0
  13. package/pipeline/skills/shared/external/hig-app-icons/evals/trigger-eval.json +22 -0
  14. package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +115 -0
  15. package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +32 -4
  16. package/pipeline/skills/shared/external/hig-components-layout/evals/evals.json +47 -0
  17. package/pipeline/skills/shared/external/hig-components-layout/evals/trigger-eval.json +22 -0
  18. package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +231 -0
  19. package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +5 -30
  20. package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
  21. package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -4
  22. package/pipeline/skills/shared/external/hig-foundations/evals/evals.json +47 -0
  23. package/pipeline/skills/shared/external/hig-foundations/evals/trigger-eval.json +21 -0
  24. package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +34 -26
  25. package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +219 -0
  26. package/pipeline/skills/shared/external/hig-inputs/SKILL.md +5 -4
  27. package/pipeline/skills/shared/external/hig-patterns/SKILL.md +19 -3
  28. package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +188 -0
  29. package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +5 -11
  30. package/pipeline/skills/shared/external/hig-platforms/SKILL.md +17 -5
  31. package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +218 -0
  32. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +4 -1
  33. package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +135 -0
  34. package/pipeline/skills/shared/external/ios-design-review/SKILL.md +146 -0
  35. package/pipeline/skills/shared/external/ios-design-review/evals/evals.json +48 -0
  36. package/pipeline/skills/shared/external/ios-design-review/evals/trigger-eval.json +22 -0
  37. package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +135 -0
  38. package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +193 -0
  39. package/pipeline/skills/shared/external/ios-haptics/SKILL.md +191 -0
  40. package/pipeline/skills/shared/external/ios-haptics/evals/evals.json +49 -0
  41. package/pipeline/skills/shared/external/ios-haptics/evals/trigger-eval.json +22 -0
  42. package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +215 -0
  43. package/pipeline/skills/shared/external/ios-iphone-duo/NOTICE.md +53 -0
  44. package/pipeline/skills/shared/external/ios-iphone-duo/SKILL.md +170 -0
  45. package/pipeline/skills/shared/external/ios-iphone-duo/evals/evals.json +50 -0
  46. package/pipeline/skills/shared/external/ios-iphone-duo/evals/trigger-eval.json +22 -0
  47. package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +212 -0
  48. package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +145 -0
  49. package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +122 -0
  50. package/pipeline/skills/shared/external/ios-sf-symbols/SKILL.md +177 -0
  51. package/pipeline/skills/shared/external/ios-sf-symbols/evals/evals.json +49 -0
  52. package/pipeline/skills/shared/external/ios-sf-symbols/evals/trigger-eval.json +22 -0
  53. package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +135 -0
  54. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +38 -50
  55. package/pipeline/skills/shared/external/swiftui-animation/evals/evals.json +47 -0
  56. package/pipeline/skills/shared/external/swiftui-animation/evals/trigger-eval.json +22 -0
  57. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +7 -73
  58. package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +185 -0
  59. package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +6 -6
  60. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +3 -253
  61. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +4 -47
  62. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +3 -111
  63. package/pipeline/skills/shared/external/swiftui-expert-skill/references/liquid-glass.md +11 -381
  64. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +184 -224
  65. package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/evals.json +47 -0
  66. package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/trigger-eval.json +22 -0
  67. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +246 -33
  68. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +227 -0
  69. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +15 -18
  70. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +1 -1
  71. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +6 -68
  72. package/pipeline/skills/skills-index.md +16 -11
  73. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +0 -786
@@ -0,0 +1,231 @@
1
+ # Bars, tabs and toolbars on iOS 26 and 27
2
+
3
+ Companion to `../SKILL.md` for the `hig-components-layout` skill. Each API
4
+ carries the iOS release it first shipped in; gate anything newer than the
5
+ deployment target with `#available`. The glass material itself (variants,
6
+ custom glass, fallbacks) is in `swiftui-liquid-glass`.
7
+
8
+ ## Contents
9
+
10
+ 1. [Content layer and navigation layer](#1-content-layer-and-navigation-layer)
11
+ 2. [Tab bars](#2-tab-bars)
12
+ 3. [Search in a tab bar or toolbar](#3-search-in-a-tab-bar-or-toolbar)
13
+ 4. [Toolbars and navigation bars](#4-toolbars-and-navigation-bars)
14
+ 5. [Overflow, priority and pinning (iOS 27)](#5-overflow-priority-and-pinning-ios-27)
15
+ 6. [Minimizing bars on scroll](#6-minimizing-bars-on-scroll)
16
+ 7. [Review checklist](#7-review-checklist)
17
+
18
+ ## 1. Content layer and navigation layer
19
+
20
+ From iOS 26, tab bars, toolbars, navigation bars and sidebars float in a
21
+ Liquid Glass layer above the content. Three consequences:
22
+
23
+ - **Keep navigation and content apart.** Destinations live in tab bars and
24
+ sidebars, actions in toolbars, and content scrolls underneath. Do not put
25
+ navigation inside content cards, or content inside bars.
26
+ - **No custom bar backgrounds.** Background images, colors and appearance
27
+ fills on `TabView`, toolbars and navigation bars sit on top of the glass and
28
+ break the scroll edge effect. Remove them and let content color the bar. Where
29
+ the bar must separate more from content, adjust
30
+ `scrollEdgeEffectStyle(_:for:)` rather than painting.
31
+ - **Tint sparingly.** Bar symbols are monochrome by default and follow the
32
+ content beneath. Over colorful content keep them monochrome, or pick an
33
+ accent that differs clearly from the content.
34
+
35
+ ## 2. Tab bars
36
+
37
+ | API | Since | What it does |
38
+ |---|---|---|
39
+ | `Tab(_:systemImage:value:content:)` | iOS 18 | A tab; keep five or fewer by default |
40
+ | `.tabViewStyle(.sidebarAdaptable)` | iOS 18 | Tab bar on iPhone, sidebar on iPad and Mac |
41
+ | `.tabBarMinimizeBehavior(_:)` | iOS 26 | `.automatic`, `.never`, `.onScrollDown`, `.onScrollUp` |
42
+ | `.tabViewBottomAccessory { }` | iOS 26 | A persistent accessory, such as a mini player, above the tab bar |
43
+ | `.tabViewBottomAccessory(isEnabled:content:)` | iOS 26.1 | The same, shown and hidden dynamically |
44
+ | `@Environment(\.tabViewBottomAccessoryPlacement)` | iOS 26 | `.expanded` above the bar or `.inline` beside a minimized bar |
45
+ | `Tab(role: .search)` | iOS 18 | The search tab; iOS 26 sets it apart at the trailing end |
46
+ | `TabRole.prominent` | iOS 27 | Prominent treatment for one tab; without one, the search tab may get it |
47
+
48
+ ```swift
49
+ TabView(selection: $selection) {
50
+ Tab("Trips", systemImage: "airplane", value: .trips) { TripsView() }
51
+ Tab("Wallet", systemImage: "wallet.pass", value: .wallet) { WalletView() }
52
+ .badge(pendingPasses)
53
+ Tab("Account", systemImage: "person.crop.circle", value: .account) { AccountView() }
54
+ Tab(value: .search, role: .search) { SearchView() }
55
+ }
56
+ .tabViewStyle(.sidebarAdaptable)
57
+ .tabBarMinimizeBehavior(.onScrollDown)
58
+ .tabViewBottomAccessory {
59
+ BoardingStatusBar()
60
+ }
61
+ ```
62
+
63
+ Accessory content adapts to its placement:
64
+
65
+ ```swift
66
+ struct BoardingStatusBar: View {
67
+ @Environment(\.tabViewBottomAccessoryPlacement) private var placement
68
+
69
+ var body: some View {
70
+ if placement == .inline {
71
+ Label("Gate B12", systemImage: "airplane.departure")
72
+ } else {
73
+ HStack {
74
+ Label("Gate B12", systemImage: "airplane.departure")
75
+ Spacer()
76
+ Text("Boarding 09:40")
77
+ }
78
+ .padding(.horizontal)
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ On iOS 27, mark the one tab that deserves emphasis. With an older deployment
85
+ target, build the iOS 27 `TabView` in its own `@available(iOS 27, *)` view and
86
+ choose between the two with `if #available`.
87
+
88
+ ```swift
89
+ Tab("Book", systemImage: "plus", value: .book, role: .prominent) {
90
+ BookingFlow()
91
+ }
92
+ ```
93
+
94
+ Rules:
95
+
96
+ - A tab switches context; never use a tab as an action ("New trip"). Only one
97
+ tab can be prominent.
98
+ - Do not hide or disable tabs because of state; explain inside the tab.
99
+ - Minimize the tab bar only when reading content benefits; people restore it
100
+ by tapping a tab or scrolling the other way.
101
+ - The accessory is for something persistent and app-wide (playback, an active
102
+ trip), not for a screen's primary action.
103
+
104
+ ## 3. Search in a tab bar or toolbar
105
+
106
+ - `Tab(role: .search)` gives search its own tab; the first tab with that role
107
+ implements search. `tabViewSearchActivation(.searchTabSelection)` (iOS 26)
108
+ activates search when the tab is selected and returns to the previous tab
109
+ when search is dismissed.
110
+ - `.searchable(text:)` on a `NavigationStack` places the field where the
111
+ platform expects; `searchToolbarBehavior(.minimize)` (iOS 26) shows the
112
+ bottom-toolbar field on iPhone as a compact button until used.
113
+ - Scopes and suggestions for large catalogs: `.searchScopes(_:scopes:)` (iOS
114
+ 16), the `activation:` form iOS 16.4, and `.searchSuggestions`.
115
+
116
+ ```swift
117
+ NavigationStack {
118
+ LibraryList(query: query, scope: scope)
119
+ .searchable(text: $query)
120
+ .searchScopes($scope) {
121
+ ForEach(LibraryScope.allCases, id: \.self) { Text($0.label).tag($0) }
122
+ }
123
+ }
124
+ ```
125
+
126
+ ## 4. Toolbars and navigation bars
127
+
128
+ | API | Since | What it does |
129
+ |---|---|---|
130
+ | Semantic placements (`.primaryAction`, `.confirmationAction`, `.cancellationAction`, `.topBarLeading`, `.topBarTrailing`, `.bottomBar`) | iOS 14 / 17 SDK | Let the system position items per platform |
131
+ | `ToolbarSpacer(.fixed)` / `ToolbarSpacer(.flexible)` | iOS 26 | Splits items into separate glass groups, or pushes groups apart |
132
+ | `.sharedBackgroundVisibility(.hidden)` | iOS 26 | Takes an item out of the shared glass group |
133
+ | `Button(role: .confirm)` / `Button(role: .close)` | iOS 26 | System confirm and close buttons in a toolbar |
134
+
135
+ ```swift
136
+ .toolbar {
137
+ ToolbarItem(placement: .cancellationAction) {
138
+ Button(role: .close) { dismiss() }
139
+ }
140
+ ToolbarItem { Button("Share", systemImage: "square.and.arrow.up", action: share) }
141
+ ToolbarItem { Button("Duplicate", systemImage: "plus.square.on.square", action: duplicate) }
142
+ ToolbarSpacer(.fixed)
143
+ ToolbarItem(placement: .confirmationAction) {
144
+ Button(role: .confirm) { save() }
145
+ }
146
+ }
147
+ ```
148
+
149
+ HIG guidance for toolbars:
150
+
151
+ - Prefer system symbols without borders to text; do not mix text and icons in
152
+ one group. Every icon still gets an accessibility label.
153
+ - One primary action, on the trailing side, with the prominent treatment.
154
+ - Aim for at most three groups; group items that act on the same thing.
155
+ - Use the standard Back and Close buttons, not custom "Back" text.
156
+ - Hide a toolbar item itself rather than the view inside it, or an empty glass
157
+ slot remains.
158
+ - Custom components inside a bar keep corner radii concentric with the bar.
159
+
160
+ ## 5. Overflow, priority and pinning (iOS 27)
161
+
162
+ | API | What it does |
163
+ |---|---|
164
+ | `ToolbarOverflowMenu { }` | Actions that always live in the toolbar's overflow menu, whatever the width; on iOS it is the navigation bar's overflow menu |
165
+ | `.toolbarOverflowMenu { }` (view modifier) | Configures that overflow menu from a view |
166
+ | `.visibilityPriority(.high)` / `.low` | When space runs out, lower-priority items move to overflow first; `ToolbarItemVisibilityPriority(higherThan:)` and `(lowerThan:)` give relative ranks |
167
+ | `ToolbarItemPlacement.topBarPinnedTrailing` | Pins an item to the trailing edge of the top bar; it moves to overflow only when search is active and space is short |
168
+
169
+ ```swift
170
+ .toolbar {
171
+ ToolbarItem(placement: .topBarPinnedTrailing) {
172
+ Button("Add", systemImage: "plus", action: add)
173
+ }
174
+ ToolbarItem { Button("Filter", systemImage: "line.3.horizontal.decrease", action: filter) }
175
+ .visibilityPriority(.high)
176
+ ToolbarItem { Button("Sort", systemImage: "arrow.up.arrow.down", action: sort) }
177
+ ToolbarOverflowMenu {
178
+ Button("Export", action: export)
179
+ Button("Print", action: printList)
180
+ }
181
+ }
182
+ ```
183
+
184
+ With an older deployment target, keep this toolbar in an
185
+ `@available(iOS 27, *)` view modifier and apply it behind `if #available`,
186
+ with a plain toolbar for earlier releases. HIG says the system adds an overflow menu by itself on
187
+ iPad and Mac when items do not fit: do not hand-build a "more" `Menu` for that,
188
+ and choose priorities so the important items stay.
189
+
190
+ ## 6. Minimizing bars on scroll
191
+
192
+ | API | Since | What it does |
193
+ |---|---|---|
194
+ | `.tabBarMinimizeBehavior(.onScrollDown)` | iOS 26 | Tab bar recedes while scrolling |
195
+ | `.toolbarMinimizationBehavior(_:for:)` | iOS 27 | Navigation bar minimizes on scroll; an integrated top tab bar minimizes with it. Supported placement: `.navigationBar` |
196
+ | `.toolbarMinimizationRestoration(.atScrollEdge, for:)` | iOS 27 | Restore only at the scroll edge (with `.onScrollDown`, navigation bar only) |
197
+ | `.toolbarMinimizationSafeAreaAdjustment(_:for:)` | iOS 27 | Whether the safe area follows the minimizing bar |
198
+
199
+ ```swift
200
+ NavigationStack {
201
+ ArticleView()
202
+ .navigationTitle("Reading")
203
+ .toolbarMinimizationBehavior(.onScrollDown, for: .navigationBar)
204
+ }
205
+ ```
206
+
207
+ Use minimization for long reading or browsing surfaces, not for forms or
208
+ screens whose bar holds the main actions.
209
+
210
+ ## 7. Review checklist
211
+
212
+ - [ ] No custom backgrounds on tab bars, toolbars or navigation bars
213
+ - [ ] Navigation in bars and sidebars, content in the content layer
214
+ - [ ] Tabs are destinations, five or fewer by default, at most one `.prominent` (iOS 27)
215
+ - [ ] Search uses `Tab(role: .search)` or `.searchable`, not a custom field in a bar
216
+ - [ ] Toolbar items use semantic placements, symbols with labels, one prominent action, groups split with `ToolbarSpacer`
217
+ - [ ] iOS 27 overflow, priority, pinning and minimization APIs are gated with `#available`
218
+ - [ ] Minimizing bars only on reading surfaces; accessory content adapts to `.inline`
219
+
220
+ Sources:
221
+ [HIG: Tab bars](https://developer.apple.com/design/human-interface-guidelines/tab-bars),
222
+ [HIG: Toolbars](https://developer.apple.com/design/human-interface-guidelines/toolbars),
223
+ [Adopting Liquid Glass](https://developer.apple.com/documentation/technologyoverviews/adopting-liquid-glass),
224
+ [tabBarMinimizeBehavior(_:)](https://developer.apple.com/documentation/swiftui/view/tabbarminimizebehavior(_:)),
225
+ [tabViewBottomAccessory(content:)](https://developer.apple.com/documentation/swiftui/view/tabviewbottomaccessory(content:)),
226
+ [TabRole.prominent](https://developer.apple.com/documentation/swiftui/tabrole/prominent),
227
+ [ToolbarOverflowMenu](https://developer.apple.com/documentation/swiftui/toolbaroverflowmenu),
228
+ [visibilityPriority(_:)](https://developer.apple.com/documentation/swiftui/toolbarcontent/visibilitypriority(_:)),
229
+ [topBarPinnedTrailing](https://developer.apple.com/documentation/swiftui/toolbaritemplacement/topbarpinnedtrailing),
230
+ [toolbarMinimizationBehavior(_:for:)](https://developer.apple.com/documentation/swiftui/view/toolbarminimizationbehavior(_:for:)),
231
+ [ToolbarSpacer](https://developer.apple.com/documentation/swiftui/toolbarspacer).
@@ -8,31 +8,9 @@ Companion to `../SKILL.md` for the `hig-components-layout` skill.
8
8
  back returns people to where they left off.
9
9
  - Never hide or disable a tab because of state. Show the tab and explain
10
10
  inside it (an empty state or sign-in prompt).
11
- - On iOS 18 and later, `Tab(role: .search)` places search as a dedicated tab;
12
- on iOS 26 it is set apart at the trailing end of the floating glass tab bar.
13
- - iOS 26 renders the tab bar as floating Liquid Glass above content. Let
14
- content scroll underneath it; do not paint an opaque background behind it.
15
- - `.tabBarMinimizeBehavior(.onScrollDown)` (iOS 26) shrinks the bar while
16
- reading; `.tabViewBottomAccessory` places a persistent control such as a
17
- playback bar above it.
18
11
  - Badges (`.badge(3)`) are for counts people act on, not marketing.
19
-
20
- ```swift
21
- TabView(selection: $selection) {
22
- Tab("Orders", systemImage: "shippingbox", value: .orders) {
23
- OrdersView()
24
- }
25
- .badge(pendingCount)
26
- Tab("Products", systemImage: "square.grid.2x2", value: .products) {
27
- ProductsView()
28
- }
29
- Tab(value: .search, role: .search) {
30
- SearchView()
31
- }
32
- }
33
- .tabViewStyle(.sidebarAdaptable)
34
- .tabBarMinimizeBehavior(.onScrollDown)
35
- ```
12
+ - Minimize behavior, the bottom accessory, the search tab and the iOS 27
13
+ prominent tab are in [bars-and-tabs.md](bars-and-tabs.md).
36
14
 
37
15
  ## Sidebars and split views
38
16
 
@@ -60,12 +38,9 @@ TabView(selection: $selection) {
60
38
 
61
39
  ## Toolbars
62
40
 
63
- - Declare actions with `.toolbar` and placements (`.primaryAction`,
64
- `.topBarTrailing`, `.bottomBar`, `.confirmationAction`,
65
- `.cancellationAction`) so the system positions them per platform.
66
- - On iOS 26 toolbar items sit on glass and are grouped automatically;
67
- `ToolbarSpacer` separates groups. Prefer SF Symbols over text for bar items
68
- and let the system apply glass; do not add your own backgrounds.
41
+ - Declare actions with `.toolbar` and semantic placements so the system
42
+ positions them per platform. Grouping, `ToolbarSpacer`, overflow, priority
43
+ and pinning are in [bars-and-tabs.md](bars-and-tabs.md).
69
44
  - Use `.toolbarRole(.editor)` on document-style screens and let people
70
45
  customise Mac and iPad toolbars with `id`-based toolbar items.
71
46
 
@@ -111,7 +111,7 @@ struct UploadRow: View {
111
111
  ## Feedback after an action
112
112
 
113
113
  - Confirm success quietly and in place: a checkmark in the button, a row that
114
- updates, a short haptic with `.sensoryFeedback(.success, trigger:)`.
114
+ updates, a short haptic (see `ios-haptics`).
115
115
  - Reserve alerts for failures that need a decision. For everything else,
116
116
  explain inline next to the thing that failed.
117
117
  - Network and sync status belongs near the affected content (a banner above
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hig-foundations
3
- description: "Apple HIG foundations mapped to SwiftUI: Dynamic Type, semantic color, contrast, safe areas, SF Symbols, materials and Liquid Glass, motion, icons, writing. Use when a design decision turns on Apple's foundations."
3
+ description: "Apple HIG foundations mapped to SwiftUI: typography and Dynamic Type, semantic color, contrast, spacing, safe areas, touch targets, motion and UX writing. Use when a design decision turns on type, color, contrast or spacing."
4
4
  metadata:
5
5
  risk: safe
6
6
  source: multi-agent-pipeline
@@ -27,13 +27,28 @@ hide problems in the steps after it.
27
27
  1. Text scales and stays readable at every size.
28
28
  2. Colors come from semantic sources and hold up in both appearances.
29
29
  3. Content respects safe areas and layout margins.
30
- 4. Icons are symbols with consistent weight and scale.
30
+ 4. Icons are symbols with consistent weight and scale (`ios-sf-symbols`).
31
31
  5. Materials and motion support the content instead of competing with it.
32
32
  6. Copy is short, specific and written in the product's voice.
33
33
 
34
+ ## The numbers that come up most
35
+
36
+ | Question | Answer (iOS and iPadOS) |
37
+ |---|---|
38
+ | Default and minimum text size | 17 pt and 11 pt, for system and custom fonts |
39
+ | Weights | Prefer Regular, Medium, Semibold, Bold; avoid Ultralight, Thin, Light |
40
+ | Second level of hierarchy inside a style | The emphasized weight via `.bold()` |
41
+ | Custom font that scales | `Font.custom(_:size:relativeTo:)`, plus `@ScaledMetric` for sizes beside text |
42
+ | Contrast | 4.5:1 for text up to 17 pt, 3:1 from 18 pt or for bold text |
43
+ | Touch target | 44 x 44 pt default, 28 x 28 pt minimum |
44
+
34
45
  ## Details on demand
35
46
 
36
- Load `references/foundations-detail.md` for each review step above, with the SwiftUI APIs and code for it.
47
+ - `references/foundations-detail.md`: each review step above with the
48
+ question to ask, the SwiftUI tools and what a reviewer looks for.
49
+ - `references/type-color-spacing.md`: the text style table with emphasized
50
+ weights, custom-font scaling, color roles, contrast table, color on Liquid
51
+ Glass, spacing scale, margins and touch targets, with code.
37
52
 
38
53
  ## Reporting findings
39
54
 
@@ -49,7 +64,11 @@ dynamicTypeSize.isAccessibilitySize.
49
64
 
50
65
  - `hig-platforms` for how these foundations shift per device.
51
66
  - `hig-components-layout`, `hig-components-content` for specific containers.
52
- - `swiftui-liquid-glass` for the iOS 26 glass APIs in depth.
67
+ - `swiftui-liquid-glass` for materials and Liquid Glass (the single owner).
68
+ - `ios-sf-symbols` for symbol rendering modes, variable values and effects.
69
+ - `hig-app-icons` for app icons, Icon Composer and appearance variants.
70
+ - `ios-accessibility` for implementing Dynamic Type, contrast and motion
71
+ settings; `ios-design-review` for checking them with screenshots.
53
72
 
54
73
  ## References
55
74
 
@@ -0,0 +1,47 @@
1
+ {
2
+ "skill_name": "hig-foundations",
3
+ "evals": [
4
+ {
5
+ "id": 0,
6
+ "name": "brand-typography-scale",
7
+ "prompt": "Our brand font is 'Moderat' and the design file uses Moderat Light 10 pt for row metadata, Moderat Thin 15 pt for body copy and hard-coded .font(.custom(\"Moderat-Bold\", size: 24)) for titles. Accessibility audit says text doesn't grow with the system setting. Rewrite our Font extension for SwiftUI and tell me what to push back on with design.",
8
+ "expected_output": "Pushes back on 10 pt (below the 11 pt iOS minimum) and on Light and Thin weights for interface text, recommending Regular or heavier and sizes at or above the defaults. Rewrites fonts with Font.custom(_:size:relativeTo:) tied to text styles (body 17 pt relative to .body, titles relative to .title or .largeTitle, metadata to .caption or .footnote), uses @ScaledMetric for adjacent dimensions, and suggests the emphasized weight via .bold() for hierarchy. Mentions checking accessibility sizes and adapting layout.",
9
+ "files": [],
10
+ "expectations": [
11
+ "Flags 10 pt as below the 11 pt iOS minimum text size",
12
+ "Advises against Light and Thin weights in favor of Regular, Medium, Semibold or Bold",
13
+ "Uses Font.custom(_:size:relativeTo:) mapped to text styles so the custom font scales with Dynamic Type",
14
+ "Mentions 17 pt as the iOS default body size",
15
+ "Mentions @ScaledMetric or adaptive layout at accessibility sizes"
16
+ ]
17
+ },
18
+ {
19
+ "id": 1,
20
+ "name": "contrast-and-color-roles",
21
+ "prompt": "Product page in SwiftUI: price in Color(hex: \"#9AA0A6\") on white at 15 pt, 'Out of stock' shown only by turning the row red, background Color.white, and a custom gray for dividers. Dark mode looks broken. What do the HIG foundations say and what do we change?",
22
+ "expected_output": "Explains the HIG minimum contrast (4.5:1 for text up to 17 pt, 3:1 for 18 pt and larger or bold), that the light gray price likely fails, and replaces hard-coded colors with semantic ones (.secondary or secondaryLabel only if contrast holds, systemBackground, separator) or asset catalog colors with light, dark and increased-contrast variants. Says out-of-stock must not be conveyed by color alone and adds a label or symbol. Mentions testing with Increase Contrast and both appearances.",
23
+ "files": [],
24
+ "expectations": [
25
+ "States the 4.5:1 minimum for text up to 17 pt (and 3:1 for larger or bold text)",
26
+ "Replaces hard-coded white and gray with semantic system colors such as systemBackground and separator, or asset colors with dark variants",
27
+ "Says color alone must not convey out-of-stock and adds text or a symbol",
28
+ "Mentions an increased-contrast variant or testing with Increase Contrast",
29
+ "Does not recommend hard-coding the documented system color values"
30
+ ]
31
+ },
32
+ {
33
+ "id": 2,
34
+ "name": "spacing-and-targets-review",
35
+ "prompt": "Review this SwiftUI row: HStack(spacing: 3) { Image(systemName: \"trash\").font(.system(size: 12)).onTapGesture(perform: delete); Text(title).font(.system(size: 13)).lineLimit(1) }.padding(.horizontal, 7). It sits in a ScrollView edge to edge on iPad too. Give findings in the foundations format.",
36
+ "expected_output": "Reports findings per foundation: the trash target is far below 44x44 pt and should become a Button with a 44 pt hit area (contentShape/frame) or use swipe actions; spacing values 3 and 7 are off any grid and should be omitted or taken from tokens or a 4 pt scale; fixed system sizes should be text styles so Dynamic Type works, and lineLimit(1) truncates at large sizes; on iPad use contentMargins or readable width instead of edge to edge. Uses the [Foundation] issue plus Fix format.",
37
+ "files": [],
38
+ "expectations": [
39
+ "Flags the tap target as below 44 x 44 pt and makes it a Button with a larger hit area",
40
+ "Replaces .system(size:) with text styles for Dynamic Type and questions lineLimit(1)",
41
+ "Flags the arbitrary 3 and 7 point values and suggests default spacing, tokens or a 4 pt scale",
42
+ "Suggests contentMargins or a readable width for iPad instead of edge-to-edge text",
43
+ "Reports each finding with the foundation name and a concrete fix"
44
+ ]
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,21 @@
1
+ [
2
+ {"query": "what's the minimum font size apple allows on iphone? design wants 9pt captions", "should_trigger": true},
3
+ {"query": "our custom font doesn't scale with dynamic type, we use Font.custom(name, size: 16) everywhere", "should_trigger": true},
4
+ {"query": "is #8E8E93 text on white ok for accessibility? it's a 14pt price label", "should_trigger": true},
5
+ {"query": "which font weights should I avoid in the app, designer loves Ultralight for headlines", "should_trigger": true},
6
+ {"query": "how much padding between rows and what margins does apple recommend, we keep guessing 7, 9, 13", "should_trigger": true},
7
+ {"query": "dark mode: our hardcoded Color.white backgrounds and gray dividers look awful, what colors should we use", "should_trigger": true},
8
+ {"query": "headline vs body vs callout - what sizes are these text styles on iOS and when do I make one bold", "should_trigger": true},
9
+ {"query": "tiny 20pt close button in the corner, testers keep missing it - what size should tap targets be", "should_trigger": true},
10
+ {"query": "status shown only with red/green dots in our order list, is that a problem per HIG", "should_trigger": true},
11
+ {"query": "make my glass toolbar buttons tinted with the brand color on iOS 26", "should_trigger": false},
12
+ {"query": "which SF Symbol rendering mode should I use for the battery icon with a level", "should_trigger": false},
13
+ {"query": "design the app icon dark and tinted variants in Icon Composer", "should_trigger": false},
14
+ {"query": "set up VoiceOver labels and rotors for our custom chart", "should_trigger": false},
15
+ {"query": "tab bar or sidebar for an iPad app with 9 sections?", "should_trigger": false},
16
+ {"query": "onboarding flow: should we ask for notification permission on first launch", "should_trigger": false},
17
+ {"query": "Material 3 typography scale for our Compose app", "should_trigger": false},
18
+ {"query": "take screenshots of the checkout screen at AX5 and dark mode and review them", "should_trigger": false},
19
+ {"query": "CSS rem vs px for our marketing site font sizes", "should_trigger": false},
20
+ {"query": "add a gentle haptic when a row is deleted", "should_trigger": false}
21
+ ]
@@ -2,6 +2,18 @@
2
2
 
3
3
  Companion to `../SKILL.md` for the `hig-foundations` skill.
4
4
 
5
+ ## Contents
6
+
7
+ - [1. Typography](#1-typography)
8
+ - [2. Color](#2-color)
9
+ - [3. Layout, margins and safe areas](#3-layout-margins-and-safe-areas)
10
+ - [4. Icons and SF Symbols](#4-icons-and-sf-symbols)
11
+ - [5. Materials, Liquid Glass and depth](#5-materials-liquid-glass-and-depth)
12
+ - [6. Motion](#6-motion)
13
+ - [7. App icon](#7-app-icon)
14
+ - [8. Writing](#8-writing)
15
+ - [9. Accessibility, as a foundation](#9-accessibility-as-a-foundation)
16
+
5
17
  ## 1. Typography
6
18
 
7
19
  Ask: if the user sets the largest accessibility text size, does every string
@@ -19,7 +31,13 @@ still fit, wrap or scroll?
19
31
  `@Environment(\.dynamicTypeSize)` and check `.isAccessibilitySize`, or use
20
32
  `ViewThatFits` to let the layout choose.
21
33
  - Keep a clear hierarchy with weight and style, not with many sizes. Two or
22
- three styles per screen is usually enough.
34
+ three styles per screen is usually enough; use a style's emphasized weight
35
+ (`.bold()`) before reaching for a bigger style.
36
+ - Respect the floor: 17 pt default and 11 pt minimum on iOS, for custom fonts
37
+ too. Avoid Ultralight, Thin and Light weights for interface text.
38
+
39
+ Numbers, the full text style table and custom-font code:
40
+ [type-color-spacing.md](type-color-spacing.md).
23
41
 
24
42
  Review signal: truncated order totals, overlapping labels, or buttons whose
25
43
  titles are clipped at `accessibility3` and above.
@@ -37,8 +55,9 @@ with increased contrast, and to someone who cannot distinguish red from green?
37
55
  - Set the app accent once with `.tint(...)` near the root; controls pick it up.
38
56
  - Never carry meaning by color alone. A failed payment shows an icon and a
39
57
  word, not only a red row.
40
- - Aim for at least 4.5:1 contrast for body text and 3:1 for large text and
41
- essential glyphs.
58
+ - Meet at least 4.5:1 contrast for text up to 17 pt and 3:1 for 18 pt and
59
+ larger or bold text; if the default palette cannot, provide a
60
+ higher-contrast scheme under Increase Contrast.
42
61
 
43
62
  Review signal: hard-coded hex values, `Color.white` text on a brand color that
44
63
  fails contrast in dark mode, status conveyed only by hue.
@@ -66,34 +85,25 @@ rounded corners and the keyboard, while backgrounds still reach the edges?
66
85
  Ask: is there a system symbol for this, and does it match the weight of the
67
86
  text beside it?
68
87
 
69
- - Use `Image(systemName:)` and `Label` so symbols align with text baselines and
70
- scale with Dynamic Type.
71
- - Pick a rendering mode on purpose: `.symbolRenderingMode(.hierarchical)` for
72
- depth, `.palette` for brand pairs, `.multicolor` where the symbol ships it.
73
- - Use `.symbolVariant(.fill)` for selected states, as tab bars do.
74
- - Animate state with `.symbolEffect` (bounce on add-to-cart, pulse while
75
- syncing) and `.contentTransition(.symbolEffect(.replace))` between glyphs.
76
- - Custom symbols belong in the asset catalog as symbol templates so they gain
77
- weights and scales like system ones.
88
+ Use `Image(systemName:)` and `Label` so symbols align with text and scale with
89
+ Dynamic Type. Rendering modes, variable values, symbol effects and custom
90
+ symbols are covered in `ios-sf-symbols`.
78
91
 
79
92
  ## 5. Materials, Liquid Glass and depth
80
93
 
81
94
  Ask: does this layer float above content, and does the content stay legible
82
95
  under it?
83
96
 
84
- - On iOS 26 and later, system bars, tab bars, sheets and toolbars adopt Liquid
85
- Glass automatically when built with standard SwiftUI containers. Avoid
86
- painting opaque backgrounds on them; that removes the effect.
87
- - For custom floating controls, apply `.glassEffect()` and group neighbors in a
88
- `GlassEffectContainer` so shapes blend and morph together. Keep glass for the
89
- navigation and control layer, not for content cards.
90
- - Use `.buttonStyle(.glass)` or `.glassProminent` for floating actions that
91
- should match system controls.
92
- - Before iOS 26, use materials (`.regularMaterial`, `.thinMaterial`) for
93
- overlays; gate newer APIs with `if #available(iOS 26, *)`.
97
+ - Liquid Glass is for the navigation and control layer; content uses standard
98
+ materials (`.ultraThinMaterial` to `.thickMaterial`) or solid fills.
99
+ - Vibrant label and fill colors keep text legible on materials; avoid the
100
+ quaternary label level on thin and ultra-thin materials.
94
101
  - Respect Reduce Transparency: system materials handle it, custom blurs must
95
102
  check `accessibilityReduceTransparency`.
96
103
 
104
+ Everything about glass itself (variants, containers, fallbacks, UIKit) lives
105
+ in `swiftui-liquid-glass`.
106
+
97
107
  ## 6. Motion
98
108
 
99
109
  Ask: does this animation explain a change, and what happens when Reduce Motion
@@ -110,10 +120,8 @@ is on?
110
120
 
111
121
  ## 7. App icon
112
122
 
113
- - Provide a single 1024 by 1024 source and let Xcode generate sizes; on iOS 18
114
- and later supply dark and tinted variants. From iOS 26, author layered icons
115
- in Icon Composer so the system can render the glass appearance.
116
- - Keep the icon a simple, recognizable shape without text or screenshots.
123
+ Layered icons, Icon Composer, the default, dark, clear and tinted appearances
124
+ and the asset catalog setup are covered in `hig-app-icons`.
117
125
 
118
126
  ## 8. Writing
119
127