@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.
- package/CHANGELOG.md +23 -0
- package/docs/facts.json +6 -6
- package/docs/features.md +1 -1
- package/install/catalog-history.json +1 -1
- package/manifest.json +85 -47
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/update/SKILL.md +2 -2
- package/pipeline/multi-agent-refs/features/usage-reporting.md +106 -67
- package/pipeline/schemas/prefs.schema.json +23 -2
- package/pipeline/scripts/usage-identity.mjs +312 -53
- package/pipeline/scripts/usage-register.mjs +204 -85
- package/pipeline/scripts/usage-report.mjs +7 -5
- package/pipeline/skills/.skill-manifest.json +35 -15
- package/pipeline/skills/.skills-index.json +66 -11
- package/pipeline/skills/shared/README.md +18 -13
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +2 -2
- package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +3 -1
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +2 -1
- package/pipeline/skills/shared/external/hig-app-icons/SKILL.md +159 -0
- package/pipeline/skills/shared/external/hig-app-icons/evals/evals.json +48 -0
- package/pipeline/skills/shared/external/hig-app-icons/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/hig-app-icons/references/icon-workflow.md +115 -0
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +32 -4
- package/pipeline/skills/shared/external/hig-components-layout/evals/evals.json +47 -0
- package/pipeline/skills/shared/external/hig-components-layout/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/hig-components-layout/references/bars-and-tabs.md +231 -0
- package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +5 -30
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -4
- package/pipeline/skills/shared/external/hig-foundations/evals/evals.json +47 -0
- package/pipeline/skills/shared/external/hig-foundations/evals/trigger-eval.json +21 -0
- package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +34 -26
- package/pipeline/skills/shared/external/hig-foundations/references/type-color-spacing.md +219 -0
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +5 -4
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +19 -3
- package/pipeline/skills/shared/external/hig-patterns/references/onboarding-and-states.md +188 -0
- package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +5 -11
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +17 -5
- package/pipeline/skills/shared/external/hig-platforms/references/ipad-layout.md +218 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +4 -1
- package/pipeline/skills/shared/external/ios-accessibility/references/large-content-and-appearance.md +135 -0
- package/pipeline/skills/shared/external/ios-design-review/SKILL.md +146 -0
- package/pipeline/skills/shared/external/ios-design-review/evals/evals.json +48 -0
- package/pipeline/skills/shared/external/ios-design-review/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/ios-design-review/references/appearance-matrix.md +135 -0
- package/pipeline/skills/shared/external/ios-design-review/references/checklist.md +193 -0
- package/pipeline/skills/shared/external/ios-haptics/SKILL.md +191 -0
- package/pipeline/skills/shared/external/ios-haptics/evals/evals.json +49 -0
- package/pipeline/skills/shared/external/ios-haptics/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/ios-haptics/references/core-haptics.md +215 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/NOTICE.md +53 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/SKILL.md +170 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/evals/evals.json +50 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/api-map.md +212 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/fixed-assumptions.md +145 -0
- package/pipeline/skills/shared/external/ios-iphone-duo/references/poses-and-panes.md +122 -0
- package/pipeline/skills/shared/external/ios-sf-symbols/SKILL.md +177 -0
- package/pipeline/skills/shared/external/ios-sf-symbols/evals/evals.json +49 -0
- package/pipeline/skills/shared/external/ios-sf-symbols/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/ios-sf-symbols/references/effects-and-custom-symbols.md +135 -0
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +38 -50
- package/pipeline/skills/shared/external/swiftui-animation/evals/evals.json +47 -0
- package/pipeline/skills/shared/external/swiftui-animation/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +7 -73
- package/pipeline/skills/shared/external/swiftui-animation/references/scroll-effects.md +185 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +6 -6
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-advanced.md +3 -253
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-basics.md +4 -47
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/animation-transitions.md +3 -111
- package/pipeline/skills/shared/external/swiftui-expert-skill/references/liquid-glass.md +11 -381
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +184 -224
- package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/evals.json +47 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/evals/trigger-eval.json +22 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +246 -33
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/uikit-glass.md +227 -0
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +15 -18
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +1 -1
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +6 -68
- package/pipeline/skills/skills-index.md +16 -11
- 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
|
|
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
|
-
|
|
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
|
|
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`
|
|
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
|
-
|
|
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
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|