@mmerterden/multi-agent-pipeline 20.17.0 → 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 (83) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/docs/facts.json +6 -6
  3. package/docs/features.md +1 -1
  4. package/install/catalog-history.json +1 -1
  5. package/manifest.json +85 -47
  6. package/package.json +1 -1
  7. package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
  8. package/pipeline/commands/multi-agent/update/SKILL.md +2 -2
  9. package/pipeline/multi-agent-refs/features/usage-reporting.md +106 -67
  10. package/pipeline/schemas/prefs.schema.json +23 -2
  11. package/pipeline/scripts/usage-identity.mjs +312 -53
  12. package/pipeline/scripts/usage-register.mjs +204 -85
  13. package/pipeline/scripts/usage-report.mjs +7 -5
  14. package/pipeline/skills/.skill-manifest.json +35 -15
  15. package/pipeline/skills/.skills-index.json +66 -11
  16. package/pipeline/skills/shared/README.md +18 -13
  17. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +2 -2
  18. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +2 -2
  19. package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +3 -1
  20. package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +2 -1
  21. package/pipeline/skills/shared/external/hig-app-icons/SKILL.md +159 -0
  22. package/pipeline/skills/shared/external/hig-app-icons/evals/evals.json +48 -0
  23. package/pipeline/skills/shared/external/hig-app-icons/evals/trigger-eval.json +22 -0
  24. package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +115 -0
  25. package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +32 -4
  26. package/pipeline/skills/shared/external/hig-components-layout/evals/evals.json +47 -0
  27. package/pipeline/skills/shared/external/hig-components-layout/evals/trigger-eval.json +22 -0
  28. package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +231 -0
  29. package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +5 -30
  30. package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
  31. package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -4
  32. package/pipeline/skills/shared/external/hig-foundations/evals/evals.json +47 -0
  33. package/pipeline/skills/shared/external/hig-foundations/evals/trigger-eval.json +21 -0
  34. package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +34 -26
  35. package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +219 -0
  36. package/pipeline/skills/shared/external/hig-inputs/SKILL.md +5 -4
  37. package/pipeline/skills/shared/external/hig-patterns/SKILL.md +19 -3
  38. package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +188 -0
  39. package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +5 -11
  40. package/pipeline/skills/shared/external/hig-platforms/SKILL.md +17 -5
  41. package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +218 -0
  42. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +4 -1
  43. package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +135 -0
  44. package/pipeline/skills/shared/external/ios-design-review/SKILL.md +146 -0
  45. package/pipeline/skills/shared/external/ios-design-review/evals/evals.json +48 -0
  46. package/pipeline/skills/shared/external/ios-design-review/evals/trigger-eval.json +22 -0
  47. package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +135 -0
  48. package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +193 -0
  49. package/pipeline/skills/shared/external/ios-haptics/SKILL.md +191 -0
  50. package/pipeline/skills/shared/external/ios-haptics/evals/evals.json +49 -0
  51. package/pipeline/skills/shared/external/ios-haptics/evals/trigger-eval.json +22 -0
  52. package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +215 -0
  53. package/pipeline/skills/shared/external/ios-iphone-duo/NOTICE.md +53 -0
  54. package/pipeline/skills/shared/external/ios-iphone-duo/SKILL.md +170 -0
  55. package/pipeline/skills/shared/external/ios-iphone-duo/evals/evals.json +50 -0
  56. package/pipeline/skills/shared/external/ios-iphone-duo/evals/trigger-eval.json +22 -0
  57. package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +212 -0
  58. package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +145 -0
  59. package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +122 -0
  60. package/pipeline/skills/shared/external/ios-sf-symbols/SKILL.md +177 -0
  61. package/pipeline/skills/shared/external/ios-sf-symbols/evals/evals.json +49 -0
  62. package/pipeline/skills/shared/external/ios-sf-symbols/evals/trigger-eval.json +22 -0
  63. package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +135 -0
  64. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +38 -50
  65. package/pipeline/skills/shared/external/swiftui-animation/evals/evals.json +47 -0
  66. package/pipeline/skills/shared/external/swiftui-animation/evals/trigger-eval.json +22 -0
  67. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +7 -73
  68. package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +185 -0
  69. package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +6 -6
  70. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +3 -253
  71. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +4 -47
  72. package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +3 -111
  73. package/pipeline/skills/shared/external/swiftui-expert-skill/references/liquid-glass.md +11 -381
  74. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +184 -224
  75. package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/evals.json +47 -0
  76. package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/trigger-eval.json +22 -0
  77. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +246 -33
  78. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +227 -0
  79. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +15 -18
  80. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +1 -1
  81. package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +6 -68
  82. package/pipeline/skills/skills-index.md +16 -11
  83. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +0 -786
@@ -0,0 +1,115 @@
1
+ # Icon workflow
2
+
3
+ Steps for building, wiring and checking an iOS app icon, with the asset
4
+ catalog route for projects that cannot move to Icon Composer yet.
5
+
6
+ ## Contents
7
+
8
+ 1. Preparing artwork
9
+ 2. Building the icon in Icon Composer
10
+ 3. Adding it to Xcode
11
+ 4. The asset catalog route
12
+ 5. Alternate icons end to end
13
+ 6. Review checklist
14
+
15
+ ## 1. Preparing artwork
16
+
17
+ - Start from the app icon template in Apple Design Resources, or set the
18
+ canvas to 1024x1024 px (1088x1088 px for Apple Watch).
19
+ - Draw layers back to front. Give them names with increasing numbers so they
20
+ import in order.
21
+ - Split colours, text and graphics you may want to adjust per appearance or
22
+ platform into their own layers.
23
+ - Convert text to outlines; SVG does not keep fonts.
24
+ - Remove blurs, shadows, specular and opacity effects, background colours and
25
+ gradients. These are set in Icon Composer, where their interaction with
26
+ Liquid Glass can be previewed.
27
+ - Export SVG. Use PNG for content SVG cannot represent. Do not export the
28
+ canvas mask.
29
+
30
+ Fully opaque layers with transparency adjusted later in Icon Composer give the
31
+ most control over how glass and transparency combine.
32
+
33
+ ## 2. Building the icon in Icon Composer
34
+
35
+ 1. Open Icon Composer (Xcode > Open Developer Tool > Icon Composer, or the
36
+ standalone download) and save the file with the name the project will use,
37
+ for example `AppIcon`.
38
+ 2. In the Document inspector, limit platforms to the ones the app ships on;
39
+ unused platform controls disappear.
40
+ 3. Drag the exported files into the sidebar. Folders become groups. Arrange
41
+ them into no more than four groups; the system renders groups as the depth
42
+ layers, bottom to top in sidebar order.
43
+ 4. Background: under Color, choose Solid or Gradient for the icon itself.
44
+ Importing a background image is rarely needed; if used, it must be
45
+ full-bleed and opaque.
46
+ 5. Liquid Glass per group: Mode (Individual or Combined), Specular
47
+ (Automatic, Inside, Outside, Off), then Blur, Refraction, Translucency and
48
+ Shadow. A layer can opt out with the Effects toggle.
49
+ 6. Appearances: use the canvas controls to preview Default, Dark and Mono.
50
+ Mono's options preview clear and tinted, light and dark, with any tint
51
+ colour. Use Vary for appearance on a setting to give one look its own
52
+ value; everything else inherits.
53
+ 7. Platforms: Composition settings (position, scale) can vary per platform
54
+ while colour and glass stay consistent.
55
+ 8. Preview against your own backgrounds (Background Image in the toolbar) and
56
+ compare rendering across system generations with the Effects controls.
57
+
58
+ ## 3. Adding it to Xcode
59
+
60
+ - Drag the Icon Composer file into the target's folder in the Project
61
+ navigator.
62
+ - In the target's General tab, under App Icons and Launch Screen, set App
63
+ Icon to the file name without its extension.
64
+ - Several Icon Composer files can live in a project (alternates); only the one
65
+ named in App Icon is the primary.
66
+ - When the deployment target includes releases without Liquid Glass icons,
67
+ Xcode generates look-alike flat images for them at build time. To keep the
68
+ previous icon on those releases, stay on the asset catalog.
69
+
70
+ ## 4. The asset catalog route
71
+
72
+ Used for tvOS and visionOS image stacks, and for iOS projects that keep their
73
+ existing icon on older releases.
74
+
75
+ - Asset catalog, add OS variant > App Icon.
76
+ - In the Attributes inspector choose **Single Size** for iOS: one 1024x1024 px
77
+ image, and Xcode generates the rest. Choose All Sizes only when a size truly
78
+ needs hand-tuned detail.
79
+ - Appearance: Any, Dark, Tinted. Provide the dark icon with a transparent
80
+ background (the system draws the backdrop) and the tinted icon as a
81
+ grayscale image. Leaving them empty uses the system's automatic treatment.
82
+
83
+ ## 5. Alternate icons end to end
84
+
85
+ 1. Create one Icon Composer file per alternate, each with its own dark, clear
86
+ and tinted treatment, and add them to the target.
87
+ 2. Build settings, Asset Catalog Compiler - Options: set **Alternate App Icon
88
+ Sets** to the alternates' names, or in an `.xcconfig`:
89
+
90
+ ```
91
+ ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = AppIcon-Night AppIcon-Mono
92
+ ```
93
+
94
+ 3. Leave `CFBundleIcons`, `CFBundlePrimaryIcon` and `CFBundleAlternateIcons`
95
+ to Xcode; it generates them from those settings.
96
+ 4. Offer the choice in the app's own settings UI with a preview of each icon,
97
+ and call `setAlternateIconName(_:)` from the person's selection. Handle the
98
+ error, and reflect `alternateIconName` as the current selection.
99
+ 5. Each alternate is reviewed by App Review like the primary icon.
100
+
101
+ In visionOS, compatible iPhone and iPad apps can still switch icons; apps
102
+ built with the visionOS SDK cannot, and the call has no effect there.
103
+
104
+ ## 6. Review checklist
105
+
106
+ - [ ] Layers are square and unmasked; nothing important near the edges.
107
+ - [ ] No baked shadows, glows, bevels or highlights.
108
+ - [ ] Recognisable in default, dark, clear and tinted looks, light and dark.
109
+ - [ ] Same core features in every appearance.
110
+ - [ ] No text unless essential; no Apple hardware; no SF Symbols.
111
+ - [ ] Crisp at small sizes (Settings, notifications, Spotlight).
112
+ - [ ] App Icon name in General matches the Icon Composer file.
113
+ - [ ] Alternates listed in Alternate App Icon Sets, each with its variants.
114
+ - [ ] Archive passes `ios_app_store_audit` asset-validation.
115
+ - [ ] Icons, alternates and in-app purchase icons suit a 4+ audience.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: hig-components-layout
3
- description: "Apple HIG for app structure mapped to SwiftUI: tab bars, split views, navigation stacks, toolbars, sheets, popovers, alerts, windows, iOS 26 Liquid Glass bars. Use when designing layout and navigation on an Apple platform."
3
+ description: "Apple HIG app structure mapped to SwiftUI: tab bars, sidebars, split views, toolbars, sheets and popovers, including the iOS 26 and 27 tab and toolbar APIs. Use when choosing navigation structure or laying out tab bars and toolbars."
4
4
  metadata:
5
5
  risk: safe
6
6
  source: multi-agent-pipeline
@@ -30,9 +30,32 @@ A tab bar switches context and never navigates within one; do not use a tab
30
30
  to trigger an action like "new note". A sidebar-adaptable `TabView` gives a
31
31
  tab bar on iPhone and a sidebar on iPad and Mac from one declaration.
32
32
 
33
+ ## Bars on iOS 26 and 27
34
+
35
+ Tab bars, toolbars, navigation bars and sidebars float in a Liquid Glass layer
36
+ over the content. Keep destinations and actions in that layer and content
37
+ underneath, and remove custom bar backgrounds: they cover the glass and the
38
+ scroll edge effect.
39
+
40
+ | Need | API (since) |
41
+ |---|---|
42
+ | Tab bar recedes while reading | `.tabBarMinimizeBehavior(.onScrollDown)` (iOS 26) |
43
+ | Persistent mini player or status above the tab bar | `.tabViewBottomAccessory { }` (iOS 26), `isEnabled:` form (iOS 26.1) |
44
+ | Search as its own tab, set apart at the trailing end | `Tab(role: .search)` (iOS 18; placement iOS 26) |
45
+ | One emphasized tab | `role: .prominent` (iOS 27) |
46
+ | Separate toolbar groups | `ToolbarSpacer(.fixed)` (iOS 26) |
47
+ | Actions that always sit in overflow | `ToolbarOverflowMenu { }` (iOS 27) |
48
+ | Which items survive a narrow bar | `.visibilityPriority(.high)` (iOS 27) |
49
+ | An item that never leaves the trailing edge | `.topBarPinnedTrailing` (iOS 27) |
50
+ | Navigation bar recedes on scroll | `.toolbarMinimizationBehavior(.onScrollDown, for: .navigationBar)` (iOS 27) |
51
+
33
52
  ## Details on demand
34
53
 
35
- Load `references/containers.md` for tab bars, sidebars, navigation bars, toolbars, scroll views, windows and size adaptation, with SwiftUI examples.
54
+ - `references/bars-and-tabs.md`: the APIs above with code, search
55
+ placement, toolbar grouping rules, overflow and minimization, and a
56
+ checklist.
57
+ - `references/containers.md`: sidebars, navigation stacks, scroll views,
58
+ windows and size adaptation, with SwiftUI examples.
36
59
 
37
60
  ## Modality: sheets, popovers, alerts
38
61
 
@@ -60,7 +83,9 @@ happen now, and always give an obvious way out.
60
83
  - Is the top-level structure chosen from the number and use of peer areas?
61
84
  - Does every tab keep its own state, and is no tab used as an action?
62
85
  - Do modals have a clear cancel, and is unsaved work protected?
63
- - Does content run under glass bars rather than behind opaque fills (iOS 26)?
86
+ - Does content run under glass bars, with no custom bar backgrounds (iOS 26)?
87
+ - Are iOS 27 bar APIs gated with `#available`, and is at most one tab
88
+ prominent?
64
89
  - Are toolbar items declared with semantic placements?
65
90
  - Does the layout adapt across size classes, windows and orientations?
66
91
 
@@ -69,7 +94,10 @@ happen now, and always give an obvious way out.
69
94
  - `hig-components-content` for lists, grids, charts inside these containers.
70
95
  - `hig-patterns` for flows such as first launch, search and settings.
71
96
  - `hig-platforms` for per-platform differences.
72
- - `swiftui-navigation` and `swiftui-liquid-glass` for implementation detail.
97
+ - `swiftui-navigation` for navigation implementation.
98
+ - `swiftui-liquid-glass` for the glass material itself.
99
+ - `hig-platforms` (`references/ipad-layout.md`) for iPad windowing and size
100
+ classes.
73
101
 
74
102
  ## References
75
103
 
@@ -0,0 +1,47 @@
1
+ {
2
+ "skill_name": "hig-components-layout",
3
+ "evals": [
4
+ {
5
+ "id": 0,
6
+ "name": "music-style-tab-bar",
7
+ "prompt": "Podcast app, SwiftUI, deployment target iOS 26. Tabs: Home, Library, Downloads, Search, plus a 'Record' tab that opens the recorder sheet. We paint the tab bar with a purple UITabBarAppearance background and want a mini player like Apple Music that stays above the tab bar and shrinks when you scroll. How should we set this up?",
8
+ "expected_output": "Removes the custom tab bar background so the floating Liquid Glass tab bar and scroll edge effect work. Uses Tab with Tab(role: .search) for search, set apart at the trailing end. Moves 'Record' out of the tab bar because a tab is not an action (toolbar button or other entry point). Uses .tabViewBottomAccessory for the mini player and .tabBarMinimizeBehavior(.onScrollDown), and adapts the accessory with the tabViewBottomAccessoryPlacement environment value (.inline vs .expanded).",
9
+ "files": [],
10
+ "expectations": [
11
+ "Removes the custom purple tab bar background",
12
+ "Uses Tab(role: .search) for the search tab",
13
+ "Says the Record tab should not be a tab because tabs are not actions",
14
+ "Uses .tabViewBottomAccessory for the mini player",
15
+ "Uses .tabBarMinimizeBehavior(.onScrollDown) and adapts the accessory via tabViewBottomAccessoryPlacement"
16
+ ]
17
+ },
18
+ {
19
+ "id": 1,
20
+ "name": "crowded-toolbar-ios27",
21
+ "prompt": "Our document editor's navigation bar on iPhone has Undo, Redo, Share, Comment, Format, Export, Print and Done buttons and half of them get clipped. We can require iOS 27 for this redesign. What should the toolbar look like in SwiftUI?",
22
+ "expected_output": "Reduces and groups items (aim for at most three groups) with ToolbarSpacer, keeps one primary Done action on the trailing side using Button(role: .confirm) or confirmationAction placement, moves rarely used actions such as Export and Print into ToolbarOverflowMenu, ranks the rest with .visibilityPriority so important items stay, and may pin a key item with .topBarPinnedTrailing. Uses symbols with accessibility labels and avoids a hand-made overflow Menu and custom bar backgrounds.",
23
+ "files": [],
24
+ "expectations": [
25
+ "Uses ToolbarOverflowMenu for rarely used actions such as Export and Print",
26
+ "Uses .visibilityPriority to control which items move to overflow first",
27
+ "Keeps a single primary Done/confirm action on the trailing side",
28
+ "Groups related items with ToolbarSpacer and keeps the number of groups small",
29
+ "Mentions .topBarPinnedTrailing or explains that iOS 27 APIs need iOS 27 availability"
30
+ ]
31
+ },
32
+ {
33
+ "id": 2,
34
+ "name": "structure-choice-ipad",
35
+ "prompt": "Field-service app: Jobs, Map, Inventory, Messages, Reports, Settings, Team, Timesheets and Documents. iPhone and iPad. Each job has a detail with parts and photos. Should this be tabs, a sidebar or something else, and how do we present 'Log time' and the job detail?",
36
+ "expected_output": "With nine peer areas recommends a sidebar-adaptable TabView (tab bar on iPhone with five or fewer primary tabs, sidebar on iPad) or NavigationSplitView, keeps Settings out of the main tabs or in a sidebar section, uses NavigationSplitView or NavigationStack for job list to detail, presents 'Log time' as a sheet with Cancel and Save and protects unsaved input with interactiveDismissDisabled, and avoids stacking modals.",
37
+ "files": [],
38
+ "expectations": [
39
+ "Recommends .tabViewStyle(.sidebarAdaptable) or a NavigationSplitView sidebar for the many areas on iPad",
40
+ "Keeps the iPhone tab bar to about five tabs and moves the rest",
41
+ "Uses a list-detail structure (NavigationSplitView or NavigationStack) for jobs",
42
+ "Presents Log time as a sheet with Cancel and a confirming action",
43
+ "Protects unsaved input or warns against stacking modals"
44
+ ]
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,22 @@
1
+ [
2
+ {"query": "how do I get a mini player above the tab bar like Apple Music in SwiftUI on iOS 26", "should_trigger": true},
3
+ {"query": "tab bar should shrink when the user scrolls down a feed, ios 26", "should_trigger": true},
4
+ {"query": "iOS 27: can I make the middle 'Create' tab look prominent like the new Photos app?", "should_trigger": true},
5
+ {"query": "navigation bar has 8 buttons and they get cut off on iphone, how do I decide what goes into the overflow menu", "should_trigger": true},
6
+ {"query": "our designer wants a solid brand-colored tab bar background on iOS 26, is that still ok?", "should_trigger": true},
7
+ {"query": "tabs or sidebar for an app with 9 sections on iPad and iPhone?", "should_trigger": true},
8
+ {"query": "ToolbarSpacer vs Spacer in toolbar - how do i split the buttons into separate glass groups", "should_trigger": true},
9
+ {"query": "should 'edit profile' be a sheet, a push or a full screen cover? and where do cancel and save go", "should_trigger": true},
10
+ {"query": "keep the Add button always visible on the trailing side of the nav bar even when search is open, iOS 27", "should_trigger": true},
11
+ {"query": "nav bar should collapse when scrolling an article on iOS 27", "should_trigger": true},
12
+ {"query": "make my custom floating button use liquid glass with a tint", "should_trigger": false},
13
+ {"query": "deep link into the third tab and push a detail screen with NavigationPath", "should_trigger": false},
14
+ {"query": "what font sizes and contrast ratios should my list rows use", "should_trigger": false},
15
+ {"query": "empty state for the downloads tab when nothing is saved yet", "should_trigger": false},
16
+ {"query": "support iPadOS 26 free-form window resizing and Stage Manager in my layout", "should_trigger": false},
17
+ {"query": "bottom sheet with medium and large detents and a grabber - how to implement the drag", "should_trigger": false},
18
+ {"query": "Compose Material 3 NavigationBar with badges", "should_trigger": false},
19
+ {"query": "tab bar icon: which SF Symbol variant should be used for the selected state", "should_trigger": false},
20
+ {"query": "React Native bottom tabs library recommendation", "should_trigger": false},
21
+ {"query": "animate the transition when switching tabs with a matched geometry effect", "should_trigger": false}
22
+ ]
@@ -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
+ }