@hegemonart/get-design-done 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +11 -5
- package/.claude-plugin/plugin.json +10 -4
- package/CHANGELOG.md +27 -0
- package/README.md +7 -0
- package/agents/design-auditor.md +5 -0
- package/agents/design-context-builder.md +6 -1
- package/agents/design-executor.md +1 -1
- package/agents/design-pattern-mapper.md +1 -0
- package/agents/design-phase-researcher.md +1 -1
- package/package.json +9 -3
- package/reference/data-visualization.md +333 -0
- package/reference/form-patterns.md +245 -0
- package/reference/information-architecture.md +255 -0
- package/reference/onboarding-progressive-disclosure.md +250 -0
- package/reference/platforms.md +346 -0
- package/reference/registry.json +402 -360
- package/reference/rtl-cjk-cultural.md +353 -0
- package/reference/user-research.md +360 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Onboarding & Progressive Disclosure
|
|
2
|
+
|
|
3
|
+
New-user experience is the highest-leverage surface in any product. A user who does not reach the aha moment in the first session almost never returns. These guidelines encode the research and failure patterns accumulated across thousands of product launches into concrete, actionable rules.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. First-Run Pattern Matrix
|
|
8
|
+
|
|
9
|
+
Four dominant patterns exist for first-run experiences. Choosing the wrong one for your product type is one of the most common causes of early churn.
|
|
10
|
+
|
|
11
|
+
| Pattern | When to use | Cognitive load | Completion rate signal | Best for product type |
|
|
12
|
+
|---|---|---|---|---|
|
|
13
|
+
| **Empty-state onboarding** | Product value is only visible once data exists; blank canvas is the default state | Low — user acts on their own terms | First meaningful action taken (e.g. first item created) | Creation tools, CRMs, project trackers |
|
|
14
|
+
| **Product tour** | Interface is dense or non-obvious; terminology requires context | Medium — user is passive during tour | Tour completion rate (misleading — see note) | Feature-rich SaaS dashboards, admin tools |
|
|
15
|
+
| **Checklist-style** | Value comes from setup completion; multiple required steps exist | Medium-high — visible task debt | Checklist completion %, items checked per session | Configuration-heavy tools, integrations |
|
|
16
|
+
| **Progressive disclosure** | Product has many features but a clear primary use case; depth should follow intent | Low at entry, scales with engagement | Feature adoption breadth over time | Consumer apps, platforms with power users |
|
|
17
|
+
|
|
18
|
+
**Empty-state onboarding** works because the blank state communicates what belongs there. A well-designed empty state — with a clear headline, one CTA, and an illustrative hint — removes the need for any separate tutorial. The first action the user takes is the onboarding. The empty state must not look like an error; it should look like an invitation. Use an illustration or icon that visually previews the populated state, so users understand what they are working toward.
|
|
19
|
+
|
|
20
|
+
**Product tours** have notoriously misleading completion metrics. A user who clicks through all seven steps of a tour has not learned the product; they have dismissed it. Tours are most defensible when they label unfamiliar terminology (e.g. "This is your Workspace — all your projects live here") rather than demonstrating features the user should simply use. If you do run a tour, keep it to five steps maximum, make every step skippable, and allow re-entry from a persistent help menu.
|
|
21
|
+
|
|
22
|
+
**Checklist-style onboarding** creates explicit visible progress. The risk is that users who skip to step 4 feel the overhead of incomplete items above them. Keep checklists short (five items maximum) and mark steps as skippable where appropriate. Celebrate completion with a visual reward. Progress bars within checklists should start at roughly 20% complete before the user takes any action — starting at zero signals a daunting amount of work ahead.
|
|
23
|
+
|
|
24
|
+
**Progressive disclosure** is the correct default for most modern products. Surface only what is needed at each stage of the user's journey and reveal depth as intent emerges. The cost of this approach is instrumentation: you must know what your users are actually doing in order to know what to surface next. Without event tracking and funnel analysis, progressive disclosure devolves into guesswork about which features to promote and when.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Feature Discovery Patterns
|
|
29
|
+
|
|
30
|
+
### Tooltip Hints
|
|
31
|
+
|
|
32
|
+
Tooltips surface contextual information at the moment of relevance without blocking interaction. Follow these placement rules strictly:
|
|
33
|
+
|
|
34
|
+
- Position tooltips above the target element by default; fall back to right, left, then below only when viewport space requires it.
|
|
35
|
+
- Never place a tooltip over the element it describes — it should annotate without obscuring.
|
|
36
|
+
- A dismiss button (×) is required on any tooltip that is not triggered by hover alone. Users must always have a clear, explicit path to close.
|
|
37
|
+
- Cap tooltip hints at **three per session**. A fourth tooltip in the same session means the user has seen enough hints that the interface should simply be better, not that more hints are needed.
|
|
38
|
+
- Do not re-show a dismissed tooltip within the same session. Respecting the dismissal is the contract.
|
|
39
|
+
|
|
40
|
+
### Spotlight / Coach Marks
|
|
41
|
+
|
|
42
|
+
Spotlight overlays draw attention to a specific UI element by dimming the surrounding interface. Use them only for genuinely non-obvious interaction points — elements whose purpose or location a reasonable user would not discover through normal exploration.
|
|
43
|
+
|
|
44
|
+
Never use coach marks for:
|
|
45
|
+
|
|
46
|
+
- Buttons with clear labels and standard placements (Save, Submit, Add)
|
|
47
|
+
- Navigation items that follow a platform convention (hamburger menu, tab bar, breadcrumb)
|
|
48
|
+
- Anything that should be self-evident from the design itself
|
|
49
|
+
|
|
50
|
+
If a feature requires a spotlight to be understood, the spotlight is a symptom. The root cause is an affordance problem in the design that should be fixed first.
|
|
51
|
+
|
|
52
|
+
### Pulsing Nudges
|
|
53
|
+
|
|
54
|
+
Animation draws the eye. That is precisely why animation budgets must be strictly managed:
|
|
55
|
+
|
|
56
|
+
- **Only one pulsing element may be active on screen at any time.** Two simultaneous pulses cancel each other's signal and create anxiety rather than direction.
|
|
57
|
+
- Stop showing the pulse after the user has seen it across **three separate sessions** without interacting. After three exposures without action, the user has seen the nudge and chosen not to act. Continuing to pulse is nagging, not guidance.
|
|
58
|
+
- Use a subtle scale pulse (1.0 → 1.08 → 1.0, ease-in-out, 1.2s, 2-second delay between cycles) rather than color flashing, which creates accessibility issues for users with photosensitive conditions.
|
|
59
|
+
- Store the "seen count" in persistent state (user record or localStorage as a fallback) so the counter survives page reloads.
|
|
60
|
+
|
|
61
|
+
### Contextual Help
|
|
62
|
+
|
|
63
|
+
Help icons, drawers, and inline `?` affordances provide depth on demand without occupying primary UI real estate:
|
|
64
|
+
|
|
65
|
+
- Place `?` icons immediately to the right of the label they annotate, at the same vertical center.
|
|
66
|
+
- Use a help drawer (slide-in panel) when the content exceeds three sentences. Modals are inappropriate for help content because they block the interface the user is trying to understand.
|
|
67
|
+
- Distinguish between hover-triggered tooltips (quick factual answers, ≤ 20 words) and click-triggered drawers (procedural explanations, examples, links to documentation).
|
|
68
|
+
- Help icons should use a consistent icon throughout the product — do not mix `?`, `ℹ`, and `…` as help affordances in the same interface.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 3. Tutorial Sequencing
|
|
73
|
+
|
|
74
|
+
### Before Value, Not Before Use
|
|
75
|
+
|
|
76
|
+
The most common tutorial design mistake is gating access to the product behind tutorial completion. This inverts the relationship between value and instruction. The correct principle is: **teach before the moment of value, not before the moment of entry.**
|
|
77
|
+
|
|
78
|
+
A user who has already experienced value will sit through a brief explanation of how to get more value. A user who has not yet experienced anything will resent being forced through a walkthrough of a product they are not yet convinced is worth their time.
|
|
79
|
+
|
|
80
|
+
Concretely: let the user reach their first meaningful outcome, then surface the "here's how to go further" guidance immediately after.
|
|
81
|
+
|
|
82
|
+
### Activation Metric vs. Habituation Metric
|
|
83
|
+
|
|
84
|
+
These two metrics measure different things and should never be conflated:
|
|
85
|
+
|
|
86
|
+
**Activation metric** — the event that indicates a user has experienced the product's core value for the first time. It is a binary event measured once. Examples: first project created, first file synced, first message sent.
|
|
87
|
+
|
|
88
|
+
**Habituation metric** — the behavioral pattern that indicates a user has formed a habit around the product. It is a frequency measure over a time window. Examples: 3 sessions per week for 4 consecutive weeks, 5 actions per session on 7 of the last 10 days.
|
|
89
|
+
|
|
90
|
+
Activation predicts retention at day 7. Habituation predicts retention at day 30 and beyond. Optimizing only for activation produces users who try the product once and never return. Optimizing for habituation without a clear activation path means most users never get far enough to form the habit.
|
|
91
|
+
|
|
92
|
+
### Tutorial Abandonment and Step Budget
|
|
93
|
+
|
|
94
|
+
Research across SaaS products consistently shows that **mean drop-off occurs at step 3** in multi-step onboarding flows. Users who reach step 4 are disproportionately engaged; steps beyond 4 reach a small fraction of users.
|
|
95
|
+
|
|
96
|
+
The implication is direct: **keep required onboarding to three steps or fewer.** Optional depth can exist beyond step 3, but nothing essential to basic product use should require more than three steps to reach.
|
|
97
|
+
|
|
98
|
+
If your product genuinely requires more than three setup steps before value is deliverable, that is a product architecture problem, not an onboarding problem.
|
|
99
|
+
|
|
100
|
+
### Deferred Tutorial
|
|
101
|
+
|
|
102
|
+
Users who land in a product for the first time are in a state of orienting, not learning. They are trying to understand whether the product is relevant to them, not how to become experts.
|
|
103
|
+
|
|
104
|
+
Surface a "Start guided tour" CTA on the **second session**, not the first. By the second session, the user has self-selected — they came back, which means something in the first session was interesting enough to return to. They are now in a learning state, not an evaluation state, and will benefit from structured guidance.
|
|
105
|
+
|
|
106
|
+
First-session tutorials should be limited to a single contextual hint or a dismissible welcome banner — not a step-by-step walkthrough.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 4. The 5-Second Rule
|
|
111
|
+
|
|
112
|
+
Within five seconds of landing on a product for the first time, users form judgments on three dimensions that are extremely difficult to revise:
|
|
113
|
+
|
|
114
|
+
1. **Value proposition clarity** — Do I understand what this product does and who it is for?
|
|
115
|
+
2. **Trust signals** — Does this look credible, maintained, and professional?
|
|
116
|
+
3. **Visual confidence** — Does the design itself inspire confidence in the product's quality?
|
|
117
|
+
|
|
118
|
+
These are not conscious evaluations. They are fast, affective responses to visual and linguistic signals. A product that fails the 5-second test loses users before any feature or flow is ever reached.
|
|
119
|
+
|
|
120
|
+
**How to test:** Show the homepage or first screen to a user for exactly five seconds (a timer-based first-click test works well). Then hide the screen and ask: "What does this product do? Who is it for? Would you trust it with your data?" Correct answers on all three indicate the screen passes.
|
|
121
|
+
|
|
122
|
+
**What passing looks like:**
|
|
123
|
+
- The headline names the outcome, not the mechanism ("Ship faster without context switching" rather than "A collaborative project management platform")
|
|
124
|
+
- At least one social proof or trust signal is visible above the fold (customer count, recognizable logo, security badge)
|
|
125
|
+
- The visual design is internally consistent — font pairing, spacing, and color are coherent enough that the product feels intentional
|
|
126
|
+
|
|
127
|
+
A screen that takes longer than five seconds to parse is not being evaluated — it is being abandoned.
|
|
128
|
+
|
|
129
|
+
**Common failures:**
|
|
130
|
+
|
|
131
|
+
| Signal | Why it fails the test |
|
|
132
|
+
|---|---|
|
|
133
|
+
| Headline is the product's name only | Communicates nothing about value or audience |
|
|
134
|
+
| Hero image is abstract or decorative | Wastes the most valuable visual real estate |
|
|
135
|
+
| No price or pricing signal | Triggers "is this for me?" uncertainty |
|
|
136
|
+
| Social proof is below the fold | Trust is not established before the judgment is made |
|
|
137
|
+
| CTA is "Learn more" | Does not indicate what action the user should take |
|
|
138
|
+
|
|
139
|
+
Run the 5-second test on every major entry point: homepage, onboarding email landing, in-app feature announcements, and pricing page. Each is a first impression for a different user segment.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 5. Aha-Moment Mapping
|
|
144
|
+
|
|
145
|
+
### Defining the Aha Moment
|
|
146
|
+
|
|
147
|
+
The aha moment is the first time a user experiences the core value the product was built to deliver. It is not a feature adoption event and not an engagement metric — it is the specific moment when the product's promise becomes real and personal to the user.
|
|
148
|
+
|
|
149
|
+
Without a defined aha moment, onboarding cannot be optimized because there is no agreed destination to optimize toward.
|
|
150
|
+
|
|
151
|
+
### Reference Examples
|
|
152
|
+
|
|
153
|
+
The most cited aha moments in product history illustrate what the concept means in practice:
|
|
154
|
+
|
|
155
|
+
- **Twitter**: Users who followed at least 10 accounts within their first 48 hours retained at a dramatically higher rate than those who did not. The aha moment was not "post a tweet" — it was "see a feed of people you actually care about."
|
|
156
|
+
- **Slack**: Teams that exchanged at least 2,000 messages retained at over 90%. The aha moment emerged from the accumulated experience of communication flow, not from any single interaction.
|
|
157
|
+
- **Dropbox**: Users who synced at least one file experienced the aha moment. The product's promise — "your files everywhere" — only became real once the first file was genuinely accessible on a second device.
|
|
158
|
+
|
|
159
|
+
In all three cases, the aha moment is an outcome state, not a feature interaction. This distinction matters for instrumentation.
|
|
160
|
+
|
|
161
|
+
### Instrumentation and Cohort Analysis
|
|
162
|
+
|
|
163
|
+
To find your product's aha moment, run the following analysis:
|
|
164
|
+
|
|
165
|
+
1. **Define candidate activation events** — identify 5–10 behavioral events that plausibly represent first value (first export, first share, first search with results, first item added, etc.).
|
|
166
|
+
2. **Build retention cohorts by activation event** — for each candidate event, create two cohorts: users who performed the event in their first session vs. users who did not. Measure day-7 and day-30 retention for each cohort.
|
|
167
|
+
3. **Identify the event with the largest retention delta** — the event whose presence most strongly predicts that users will still be active 30 days later is your aha moment proxy.
|
|
168
|
+
4. **Validate with qualitative research** — confirm with user interviews that users who performed the event actually experienced a moment of genuine value, not just navigated through a flow.
|
|
169
|
+
5. **Reduce the time-to-aha** — once the event is identified, redesign onboarding to move the user toward that event as quickly as possible, removing every unnecessary step in between.
|
|
170
|
+
|
|
171
|
+
The aha moment is a hypothesis that must be re-evaluated as the product evolves. A feature change or new user segment can shift the activation event.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 6. Anti-Patterns
|
|
176
|
+
|
|
177
|
+
### Forced Tours
|
|
178
|
+
|
|
179
|
+
A forced tour blocks access to the product until the user completes a tutorial sequence. This pattern consistently destroys retention because it starts the relationship with a power imbalance: the product demands the user's time before delivering any value in return.
|
|
180
|
+
|
|
181
|
+
Users who complete forced tours do so under duress, not interest. Their completion rate looks healthy in analytics, but their recall of tour content is near zero. More critically, the forced-tour experience establishes a negative first emotional association with the product that carries forward into subsequent sessions.
|
|
182
|
+
|
|
183
|
+
**Never gate the product behind tutorial completion.** The skip button is not a concession — it is a requirement.
|
|
184
|
+
|
|
185
|
+
### Blocking Modal Overlays
|
|
186
|
+
|
|
187
|
+
Modal overlays that cover the interface to display instructional content are problematic on two grounds. First, they prevent the user from interacting with the very interface they are being instructed about — learning by doing is impossible when the interface is obscured. Second, full-screen modal overlays frequently fail WCAG 2.1 Success Criterion 1.3.4 (Orientation) and 2.1.2 (No Keyboard Trap) when implemented without proper focus management, making them inaccessible to keyboard and screen reader users.
|
|
188
|
+
|
|
189
|
+
Use inline empty states, contextual tooltips, or side drawers for instructional content. Reserve modals for actions that require a decision before proceeding, not for passive information delivery.
|
|
190
|
+
|
|
191
|
+
### Tooltip Spam
|
|
192
|
+
|
|
193
|
+
Displaying more than three tooltips simultaneously creates cognitive overload. The user cannot process multiple concurrent annotations — they will either dismiss all of them without reading or abandon the session. Three concurrent tooltips is already at the upper threshold of what users will tolerate; two is better; one is the correct default.
|
|
194
|
+
|
|
195
|
+
If your interface requires more than three tooltips to be usable, the interface needs redesign, not more tooltips.
|
|
196
|
+
|
|
197
|
+
### Feature Announcements on Every Login
|
|
198
|
+
|
|
199
|
+
Surfaces that display feature announcement banners, modals, or toasts on every login train users to dismiss without reading. After two or three sessions of seeing a banner, dismissal becomes an automatic motor behavior, not a reading behavior. This renders the announcement channel useless for future communications that actually matter.
|
|
200
|
+
|
|
201
|
+
Feature announcements should be shown once per feature, in context (near the new feature), and only to users for whom the feature is relevant. A user who has never used the reporting module should not see an announcement about reporting improvements.
|
|
202
|
+
|
|
203
|
+
### Onboarding for Features They Did Not Request
|
|
204
|
+
|
|
205
|
+
Proactively onboarding users to features they have not expressed interest in violates their intent. A user who opened the product to complete a specific task and is instead walked through an unrelated feature experiences the tutorial as an interruption, not a benefit.
|
|
206
|
+
|
|
207
|
+
Progressive disclosure exists precisely to prevent this: surface depth in response to observed intent, not on a broadcast schedule. If a user navigates to a feature for the first time, that is the correct moment to offer brief guidance. If they have never navigated to it, it is not the correct moment to introduce it.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 7. Measuring Onboarding Health
|
|
212
|
+
|
|
213
|
+
Onboarding is only improvable if it is measured. The following metrics form the minimum instrumentation layer for any product with an intentional onboarding strategy.
|
|
214
|
+
|
|
215
|
+
**Time-to-activation** measures how long it takes a new user to reach the defined activation event from their first login. Expressed as a median and p75 (the slowest 25% of activating users). A rising time-to-activation without a corresponding increase in activation rate indicates that the activation path has grown longer or more confusing.
|
|
216
|
+
|
|
217
|
+
**Activation rate** is the percentage of new users who reach the activation event within a defined window (typically 7 days). Baseline activation rates vary widely by product category, but any activation rate below 40% warrants investigation. An activation rate above 70% is a strong signal.
|
|
218
|
+
|
|
219
|
+
**Onboarding funnel drop-off** tracks step-by-step completion rates through any sequential onboarding flow. Every step should be instrumented individually. Drop-off above 30% at any single step is a red flag requiring immediate qualitative investigation — user interviews, session recordings, or both.
|
|
220
|
+
|
|
221
|
+
**Feature discovery breadth** measures how many distinct features or feature areas a user touches in their first 14 days. Low breadth in early sessions is not necessarily a problem — focused users often have the highest retention — but anomalously low breadth combined with low retention indicates that users are not finding the product's range of value.
|
|
222
|
+
|
|
223
|
+
| Metric | Healthy range | Warning threshold |
|
|
224
|
+
|---|---|---|
|
|
225
|
+
| Time-to-activation (median) | < 5 minutes | > 20 minutes |
|
|
226
|
+
| Activation rate (7-day) | > 50% | < 30% |
|
|
227
|
+
| Step drop-off (any single step) | < 20% | > 35% |
|
|
228
|
+
| Day-7 retention | > 40% | < 20% |
|
|
229
|
+
| Day-30 retention | > 20% | < 10% |
|
|
230
|
+
|
|
231
|
+
These thresholds are reference points drawn from cross-industry SaaS benchmarks. They will vary by product category, pricing model, and acquisition channel. Calibrate against your own historical baseline before treating any single number as universal.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Quick-Reference Decision Rules
|
|
236
|
+
|
|
237
|
+
The rules below consolidate the most common judgment calls into explicit thresholds. Apply them as defaults; deviate only with data.
|
|
238
|
+
|
|
239
|
+
| Question | Rule |
|
|
240
|
+
|---|---|
|
|
241
|
+
| How many tooltip hints per session? | Maximum 3 |
|
|
242
|
+
| How many pulsing elements on screen? | Maximum 1 |
|
|
243
|
+
| How many steps in required onboarding? | Maximum 3 |
|
|
244
|
+
| When to surface guided tour CTA? | Second session, not first |
|
|
245
|
+
| When to stop showing a pulsing nudge? | After 3 sessions seen without interaction |
|
|
246
|
+
| Can a tutorial block product access? | Never |
|
|
247
|
+
| How many concurrent tooltips? | Maximum 1 (hard ceiling 3) |
|
|
248
|
+
| How often to repeat a feature announcement? | Once per feature, in context |
|
|
249
|
+
| What determines the aha moment? | Largest day-30 retention delta across cohorts |
|
|
250
|
+
| What does passing the 5-second test require? | Correct answers on value, audience, and trust |
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# Platforms — Reference Guide
|
|
2
|
+
|
|
3
|
+
Platform conventions are not arbitrary constraints — they are the accumulated result of billions of user interactions on each operating system. When a designer deviates from a platform convention, they are implicitly asking their user to unlearn a trained reflex and replace it with a novel one specific to this product. That is expensive. This reference establishes the canonical interaction patterns, layout rules, gesture vocabularies, and component conventions for each platform the get-design-done framework targets, along with the governing rule for when brand expression should yield to platform habit and when it should not.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Navigation Patterns by Platform
|
|
8
|
+
|
|
9
|
+
Navigation is the skeleton of a product. Getting it wrong does not just inconvenience users — it makes the entire product feel alien on its own operating system. Each platform has developed a navigation idiom that users practice dozens of times per day across every app on the device. A product that violates that idiom creates friction on every single screen transition.
|
|
10
|
+
|
|
11
|
+
### iOS
|
|
12
|
+
|
|
13
|
+
iOS navigation is built on a two-axis model: vertical hierarchy (drilling into content via a navigation stack managed by `UINavigationController` or SwiftUI's `NavigationStack`) and lateral switching (jumping between top-level sections via a `UITabBarController` or SwiftUI's `TabView`). The tab bar lives at the bottom of the screen and should contain between two and five destinations. Apple's Human Interface Guidelines are explicit that five tabs is the maximum — adding a sixth requires a "More" overflow pattern, which is a recognized user experience penalty.
|
|
14
|
+
|
|
15
|
+
The navigation bar at the top of the screen carries the current screen title and back button. The back button is automatically generated by the navigation stack with the title of the previous screen as its label when space permits, falling back to the word "Back." Never replace the system back button with a custom left-side icon that performs a different action — this violates user expectation so severely that it creates support tickets.
|
|
16
|
+
|
|
17
|
+
Hamburger menus (three-line "sandwich" icons triggering a side drawer) are a web and Android import. They are not idiomatic iOS and should not appear in native iOS apps. If a product has more destinations than five tabs can accommodate, the correct iOS solution is to reconsider the information architecture, not to add a drawer. Drawers exist in some iOS apps, but they are third-party patterns tolerated for legacy reasons, not blessed conventions.
|
|
18
|
+
|
|
19
|
+
### Android
|
|
20
|
+
|
|
21
|
+
Android follows Material 3's navigation component system. The bottom navigation bar serves the same function as iOS's tab bar — lateral switching between top-level destinations — and should contain three to five destinations. Material 3 introduced the navigation rail as the preferred navigation surface on medium-width screens (tablets, foldables in unfolded state), where it appears as a vertical column of icons and labels on the leading edge of the layout. On large screens (desktop-class Android, Chromebook), a navigation drawer — either modal or persistent — replaces the rail.
|
|
22
|
+
|
|
23
|
+
The system back gesture on Android is an edge swipe from either the left or right side of the screen. Since Android 10 this is the system default, replacing the software back button in gesture navigation mode. Designs must never shadow this gesture with in-app behavior, because the OS intercepts it before the app's gesture recognizers fire. The back gesture always navigates up in the activity/fragment back stack or returns to the launcher; no design override is possible or appropriate.
|
|
24
|
+
|
|
25
|
+
### Web
|
|
26
|
+
|
|
27
|
+
Web navigation has three dominant patterns, each suited to a different information architecture scale. Top navigation bars work for sites with five to eight primary sections whose names fit comfortably in a single horizontal row. Sidebars are the standard for application-density products (dashboards, admin tools, documentation sites) because they accommodate ten to thirty labeled destinations without cognitive overload, and they scale with the viewport rather than breaking. Mega-menus — large overlay panels triggered by hovering or clicking a top-nav item — suit e-commerce and marketing sites where category hierarchies are deep but users need cross-category discovery on every page.
|
|
28
|
+
|
|
29
|
+
The command palette, triggered by `Cmd+K` (macOS) or `Ctrl+K` (Windows/Linux), has become the power-user navigation layer for application-dense web products. It is not a replacement for structural navigation — it is an accelerator for users who already know where they want to go. Implementing a command palette without maintaining the sidebar or top nav for discoverability is a mistake; command palettes serve learners and experts differently, and both populations need to be served simultaneously.
|
|
30
|
+
|
|
31
|
+
### visionOS
|
|
32
|
+
|
|
33
|
+
visionOS inhabits three-dimensional space, and its navigation conventions emerge from the affordances of spatial UI. Users look around and glance at windows rather than tapping a nav bar, so the concept of a persistent bottom bar — physically below the user's comfortable resting gaze — is inappropriate. Apple's spatial design guidelines introduce orbital menus: radial arrangements of controls that anchor to content and appear at the periphery of a window when activated, keeping the central content area unobstructed.
|
|
34
|
+
|
|
35
|
+
Window grouping is the visionOS analog of tab groups. Related windows can be positioned in the user's space as a coherent cluster, and the user navigates between them by glancing and reaching. The design implication is that each window should be self-sufficient and not require persistent navigation chrome — navigation is spatial rather than embedded in a UI surface. Because users can position windows anywhere in their environment, designers cannot rely on spatial relationships that were composed in the design tool; design for each window independently, not for a composed layout.
|
|
36
|
+
|
|
37
|
+
### watchOS
|
|
38
|
+
|
|
39
|
+
watchOS navigation is scroll-first. The primary navigation surface is a scrollable list — the watch equivalent of a `UITableView` — optimized for the Digital Crown, which provides physical momentum scrolling. Users expect to scroll down to see more content on the current screen and to use the Digital Crown as the primary navigation gesture for list content. Tapping the Digital Crown navigates to the watch face; this gesture is reserved by the OS and cannot be shadowed.
|
|
40
|
+
|
|
41
|
+
Nested navigation should never exceed two levels on watchOS. The small screen area and the awkward input model (small touch targets, no text input without Siri) mean that deep navigation hierarchies become traps — users lose orientation and cannot easily escape. If a feature cannot be expressed in two navigation levels or fewer, it is too complex for watchOS and should be redesigned or moved to the companion iOS app.
|
|
42
|
+
|
|
43
|
+
### Cross-Platform Consistency: Convention vs. Brand
|
|
44
|
+
|
|
45
|
+
The governing rule for resolving the tension between platform convention and brand identity is this: **follow the platform for navigation, interaction patterns, and component behavior; apply the brand to color, typography scale, iconography, and illustration.** A user who encounters a bottom tab bar on iOS and a bottom navigation bar on Android is experiencing appropriate platform adaptation, not inconsistent branding. A user who encounters a custom gesture that conflicts with the OS back gesture is experiencing a design error, regardless of how on-brand the interaction felt in the design tool.
|
|
46
|
+
|
|
47
|
+
Brand consistency lives in the visual layer — your colors, type choices, illustration style, and motion language should be recognizable across platforms without requiring you to break platform idioms to achieve them. When a component does not exist in your design system for a given platform (for example, a native alert dialog on iOS vs. Android), the correct approach is to adapt the component to the platform's idiom while keeping the copy, color, and brand voice consistent.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 2. Safe Areas and Layout Margins
|
|
52
|
+
|
|
53
|
+
Every modern mobile platform introduces areas of the display where UI elements should not appear: behind the status bar, under the home indicator, behind the camera cutout, or outside the circular mask of a watch. Ignoring safe areas does not merely produce visual bugs — it can make controls unreachable or occluded in ways that break the product for large segments of users.
|
|
54
|
+
|
|
55
|
+
### iOS: Notch, Dynamic Island, and Home Indicator
|
|
56
|
+
|
|
57
|
+
Since the iPhone X, iOS devices have a camera housing at the top of the display — originally the notch, now the Dynamic Island on newer devices — and a home indicator bar at the bottom. iOS exposes these as safe area insets, accessible in CSS via the environment function:
|
|
58
|
+
|
|
59
|
+
```css
|
|
60
|
+
padding-top: env(safe-area-inset-top);
|
|
61
|
+
padding-right: env(safe-area-inset-right);
|
|
62
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
63
|
+
padding-left: env(safe-area-inset-left);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For web content rendered in a WKWebView or Safari on iOS, the viewport meta tag must include `viewport-fit=cover` to opt in to edge-to-edge layout; without it, the browser automatically adds padding and the environment variables resolve to zero, making them useless:
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The home indicator at the bottom of the display on Face ID devices occupies approximately 34 points. Any interactive controls placed at the very bottom of the screen — primary action buttons, persistent toolbars, bottom sheets — must clear the home indicator. The system automatically applies the inset for native UIKit and SwiftUI layouts, but web-in-WebView requires the CSS above. Failing to handle the bottom inset is the single most common iOS layout bug in hybrid apps.
|
|
73
|
+
|
|
74
|
+
### Android: Status Bar, Navigation Bar, and Edge-to-Edge
|
|
75
|
+
|
|
76
|
+
Android has enforced edge-to-edge rendering as the default since Android 15. Prior to this, apps could opt out of drawing behind the system bars; that escape hatch is now closed. Every app draws behind the status bar and the gesture navigation bar, and every app is responsible for inset handling.
|
|
77
|
+
|
|
78
|
+
Android exposes insets through `WindowInsetsCompat` in the Jetpack library. In Jetpack Compose, the `safeDrawing` inset padding modifier handles the most common cases. For React Native and Flutter apps targeting Android, the platform bridge handles inset forwarding, but custom navigation bars or bottom sheets still require explicit inset consumption.
|
|
79
|
+
|
|
80
|
+
The system gesture navigation bar at the bottom of the screen is transparent by default on Android 10 and later, showing the app content beneath it. This means a white bottom sheet on a white background will appear to have no bottom boundary — the bar blends in. The design solution is to draw content under the bar (which Android encourages) while ensuring the bottommost interactive control is above the gesture exclusion zone, which is approximately 30dp from the bottom edge.
|
|
81
|
+
|
|
82
|
+
### Web: Viewport Units and Browser Chrome Behavior
|
|
83
|
+
|
|
84
|
+
The `100vh` viewport unit on mobile browsers has been a source of layout bugs for years. Mobile browsers (Safari on iOS, Chrome on Android) subtract their toolbar chrome from the viewport when the toolbar is shown, then restore that height when the toolbar hides as the user scrolls down. A bottom bar positioned at `bottom: 0; height: 100vh` will appear to jump as the browser chrome appears and disappears.
|
|
85
|
+
|
|
86
|
+
The correct unit is `dvh` (dynamic viewport height), introduced in the CSS Values Level 4 specification and supported in all modern mobile browsers as of 2023. `100dvh` tracks the visible viewport including chrome behavior. For elements that should be full-screen and must not resize, use `svh` (small viewport height, the minimum height when chrome is fully visible). For elements that should use all available space when chrome is hidden, use `lvh` (large viewport height). The table below summarizes:
|
|
87
|
+
|
|
88
|
+
| Unit | Resolves to | Use case |
|
|
89
|
+
|------|-------------|----------|
|
|
90
|
+
| `100vh` | Static — initial viewport height, ignores chrome | Avoid on mobile; use for desktop |
|
|
91
|
+
| `100dvh` | Dynamic — updates as browser chrome shows/hides | Default choice for full-height mobile layouts |
|
|
92
|
+
| `100svh` | Static — smallest possible viewport (chrome fully visible) | Fixed bottom bars that should never resize |
|
|
93
|
+
| `100lvh` | Static — largest possible viewport (chrome fully hidden) | Hero sections that expand when chrome hides |
|
|
94
|
+
|
|
95
|
+
### watchOS: Circular Display Mask
|
|
96
|
+
|
|
97
|
+
The Apple Watch display has rounded corners and a circular mask that clips content outside a rounded-rectangle boundary on older models and an increasingly circular boundary on newer always-on display models. Content placed in the extreme corners of a 44mm or 45mm Watch layout will be clipped. The standard layout margin in SwiftUI on watchOS is 6pt on each horizontal edge; content within this margin is guaranteed to be visible. Images and full-bleed backgrounds should be designed to be visually effective even when corners are clipped.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 3. Gesture Vocabularies
|
|
102
|
+
|
|
103
|
+
Gestures are the physical language of a platform. Each operating system has reserved certain gestures for system-level navigation, and these reservations cannot be overridden by applications — the OS claims them before the app's gesture recognizers run. Shadowing a reserved gesture does not produce a conflict; it produces a silent failure where the user's intended in-app action triggers the system behavior instead, and the app gesture is never received.
|
|
104
|
+
|
|
105
|
+
### iOS Gesture Reservations
|
|
106
|
+
|
|
107
|
+
The most critical reserved gesture on iOS is the **swipe from the left edge of the screen**, which navigates back in the navigation stack. Any custom pan gesture that begins near the left edge will conflict with the system's interactive pop gesture recognizer. The correct handling is to disable the custom gesture when it would conflict, not to attempt to override the system behavior.
|
|
108
|
+
|
|
109
|
+
**Swipe down from the top of the screen** opens Notification Center. On Face ID devices, swiping down from the upper-left opens Notification Center and swiping down from the upper-right opens Control Center. Custom pull-to-refresh gestures that begin at the very top of the screen work because they begin from within the scrollable content area, not from the status bar region.
|
|
110
|
+
|
|
111
|
+
**Long press** on iOS surfaces context menus (UIContextMenu) or enters wiggle mode on home screen icons. In-app long press for custom behavior is acceptable as long as it is not the primary or only affordance for a critical action — users cannot discover long-press affordances without experimentation, so any feature requiring long press must also be reachable through a visible control.
|
|
112
|
+
|
|
113
|
+
**Pinch** zooms content in maps, images, and text. Applications can use pinch for custom scaling behaviors within a content view, but pinch should not be used as a navigation trigger (e.g., pinch to go back) because it conflicts with system-level zoom accessibility features.
|
|
114
|
+
|
|
115
|
+
**Force Touch / Haptic Touch** (long press with haptic response) is the iOS mechanism for quick actions and peek. It is available on all modern iOS devices. Use UIContextMenuInteraction for this behavior rather than attempting to detect touch pressure manually — the system API handles the haptic response and the visual presentation.
|
|
116
|
+
|
|
117
|
+
### Android Gesture Reservations
|
|
118
|
+
|
|
119
|
+
The **edge swipe from either the left or right side of the screen** navigates back in the activity stack. This is identical in function to iOS's left-edge swipe but applies to both edges on Android. Applications can declare gesture exclusion rectangles — specific screen regions where the app claims swipe gestures — but these are limited to a maximum height of 200dp per region and cannot occupy the full screen height. Use gesture exclusion only for essential in-app swipe interactions like sliders and carousels that are positioned near the screen edge.
|
|
120
|
+
|
|
121
|
+
**Swipe up from the bottom** opens the app launcher/home screen or enters recents mode, depending on how far the swipe extends. This gesture cannot be intercepted or overridden by applications. Bottom sheets that need to be dragged upward must begin from a handle or content area clearly above the system gesture zone.
|
|
122
|
+
|
|
123
|
+
**Long press** on Android surfaces the contextual action menu and is widely used for multi-select patterns. Applications using long press for multi-select should follow Material Design's contextual action bar pattern — replacing the top app bar with an action bar that shows selection actions and a count of selected items.
|
|
124
|
+
|
|
125
|
+
### Web Gesture Considerations
|
|
126
|
+
|
|
127
|
+
Web applications run inside a browser, which itself manages scroll, zoom, and navigation gestures. The `touch-action` CSS property allows web applications to declare which gestures they handle natively, preventing the browser from consuming those gestures. For a swipeable carousel, setting `touch-action: pan-y` tells the browser to handle vertical scrolling and pass horizontal swipes to the app's event listeners.
|
|
128
|
+
|
|
129
|
+
**Two-finger scroll** on trackpads and touchscreens is reserved for page scrolling and cannot be reliably shadowed for in-app use. Horizontal two-finger swipe in browsers navigates browser history (back/forward). Applications that use horizontal swipe for in-content navigation should be aware that this gesture will also trigger history navigation on some browser/OS combinations — a usability bug that is difficult to resolve without harming native browser back behavior.
|
|
130
|
+
|
|
131
|
+
### visionOS Gesture Vocabulary
|
|
132
|
+
|
|
133
|
+
visionOS uses eye tracking combined with hand gestures. The primary interaction is look-and-tap: the user looks at a control (which highlights with a hover effect driven by eye tracking) and then performs a pinch gesture with thumb and index finger to activate it. Spatial pinch is the visionOS equivalent of a mouse click and should be treated as such — buttons and interactive controls designed for iOS translate directly.
|
|
134
|
+
|
|
135
|
+
**Drag** is performed by looking at a draggable element, pinching to grab, and moving the hand. Applications should not create drag interactions that require precise or sustained hand movement — the physical effort is significantly higher than a mouse drag, and prolonged gestures cause arm fatigue.
|
|
136
|
+
|
|
137
|
+
### watchOS Gesture Vocabulary
|
|
138
|
+
|
|
139
|
+
The **Digital Crown** rotation is the signature watchOS input. It scrolls lists, adjusts values, and zooms maps. The Digital Crown single press navigates to the watch face; this is an absolute OS reservation. The Digital Crown button-press behavior cannot be customized by applications on watchOS.
|
|
140
|
+
|
|
141
|
+
**Horizontal swipes** navigate between pages in a PageTabViewStyle layout, which is the watchOS equivalent of a paged scroll view. This is the appropriate pattern for content that has a natural left-right sequence (steps in a process, days in a week). For non-sequential content, the scrollable list is preferable.
|
|
142
|
+
|
|
143
|
+
**Vertical swipes within a scrollable list** are the standard content navigation gesture and should not be given custom meaning. Applications that intercept vertical swipe for their own purposes will prevent list scrolling, which breaks the fundamental navigation model of the platform.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 4. Platform-Specific Component Conventions
|
|
148
|
+
|
|
149
|
+
Components carry platform affordances encoded in their shape, behavior, and position. Using the wrong component variant on a given platform is not merely a visual inconsistency — it communicates a different action or intent to the user because the component's meaning is partially derived from its platform context.
|
|
150
|
+
|
|
151
|
+
### Action Sheet vs. Bottom Sheet
|
|
152
|
+
|
|
153
|
+
On iOS, the action sheet (`UIActionSheet`, or `actionSheet` in SwiftUI) presents a set of choices related to the current context, anchored to the bottom of the screen on iPhone and presented as a popover on iPad. Action sheets are for choosing between a set of actions — they are not for arbitrary content. The Cancel button is always present at the bottom of the sheet and is the escape route.
|
|
154
|
+
|
|
155
|
+
On Android, the equivalent is the modal bottom sheet from Material Design. It serves a broader role than the iOS action sheet: it can contain lists of actions, but also form fields, detail content, or navigation. The Android bottom sheet does not have a mandatory Cancel button in the same position; instead, it is dismissed by tapping the scrim outside or by dragging it down. This behavioral difference means designs cannot be directly translated — an iOS action sheet with a prominent Cancel button will look wrong on Android because the dismiss convention differs.
|
|
156
|
+
|
|
157
|
+
### Alert Dialog vs. Dialog
|
|
158
|
+
|
|
159
|
+
An iOS `UIAlertController` in alert style is a small centered dialog with a title, message, and up to two action buttons. When there are more than two actions, use the action sheet instead — the iOS alert is intentionally constrained to binary decisions. Alert dialogs block all interaction until dismissed.
|
|
160
|
+
|
|
161
|
+
Android's AlertDialog from Material Design is visually similar but accepts up to three buttons (positive, negative, neutral) and supports more complex layouts including dividers and scrollable content. The Android dialog also uses stronger typographic hierarchy than iOS alerts, following Material's `Title/Body/Actions` pattern explicitly.
|
|
162
|
+
|
|
163
|
+
Neither platform's alert dialog is appropriate for complex content, form input, or multi-step flows. For those, iOS uses presentation-style modal view controllers (full-screen or sheet), and Android uses full-screen dialogs or bottom sheets.
|
|
164
|
+
|
|
165
|
+
### iOS Segmented Control vs. Android Tab Row
|
|
166
|
+
|
|
167
|
+
The iOS segmented control is a compact selector for switching between two to five mutually exclusive views or modes. It appears inline in the content area or in navigation bars, and its selection is reflected immediately — it is not a submit-style control. The segmented control is visually contained within a pill shape and does not have separate tab indicator lines.
|
|
168
|
+
|
|
169
|
+
Android's equivalent is the Tab layout from Material Design, which uses underline indicators on a row of text labels. Material 3 distinguishes between primary tabs (page-level navigation) and secondary tabs (content filtering within a page). The visual language is different enough that using an iOS segmented control design on Android will read as foreign. Design platform-specific variants for each; share only the component's logic and data model.
|
|
170
|
+
|
|
171
|
+
### iOS Switch vs. Android Toggle
|
|
172
|
+
|
|
173
|
+
The iOS switch (UISwitch) is a pill-shaped binary toggle with a white circle thumb that slides horizontally. The on state uses the system accent color (blue by default). The animation is a smooth horizontal slide that makes the state change unambiguous.
|
|
174
|
+
|
|
175
|
+
Android's Material Design switch uses the same horizontal sliding metaphor but has a distinct visual grammar: a larger thumb that grows when dragged, an optional checkmark icon inside the thumb for the on state, and icon support for communicating the off state as well. Material 3 switches also support rounded and squircle thumb variants. The behavioral intention is identical, but the visual design is different enough that the components should be implemented separately per platform rather than sharing a single cross-platform design token.
|
|
176
|
+
|
|
177
|
+
### Web Modal vs. Native Sheet
|
|
178
|
+
|
|
179
|
+
A web modal dialog (the HTML `<dialog>` element, or a custom overlay) blocks page interaction behind a scrim and centers a card in the viewport. It is the correct choice for confirmations, forms that require focus, and content previews when the user needs to complete or dismiss a task before continuing. Web modals work on both mouse and touch interfaces because they do not depend on the physical affordance of dragging a sheet from a panel edge.
|
|
180
|
+
|
|
181
|
+
Native bottom sheets (half-modal sheets in iOS, bottom sheets in Android) are appropriate for mobile-width layouts where the card anchored to the screen bottom provides a tactile affordance — users can drag the sheet down to dismiss it. On web, native sheet behavior can be approximated with CSS transitions and touch event handling, but it requires explicit engineering to match the physics of the native implementation. Reserve the sheet pattern for mobile web experiences; use centered modals for desktop web where sheets feel out of place.
|
|
182
|
+
|
|
183
|
+
### visionOS: Ornaments vs. Toolbars
|
|
184
|
+
|
|
185
|
+
visionOS introduces the concept of ornaments — UI elements that appear to float outside the boundary of a window, anchored to its edge. The primary toolbar of a visionOS window should be placed in an ornament rather than inside the window's content area. This keeps the window's content area clean and takes advantage of the spatial depth available in visionOS to create a sense of UI layering. Toolbars inside windows flatten the spatial affordance of the platform and feel like web content rather than native visionOS design.
|
|
186
|
+
|
|
187
|
+
SwiftUI surfaces ornaments through the `.ornament` modifier, which anchors to a specified edge of the window at a specified offset. The recommended pattern is to place navigation controls (back, close, minimize) and contextual actions (edit, share, refresh) in an ornament anchored to the bottom or leading edge of the content window.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 5. Native Typography
|
|
192
|
+
|
|
193
|
+
Platform typography is not merely a default font choice — it is a system of optical sizes, weights, tracking values, and dynamic scaling behaviors that the platform vendor has spent years calibrating for their display hardware. Using the native type system correctly means the product's text will look and respond identically to text in the OS and every other native app, which is the baseline users calibrate their reading experience against.
|
|
194
|
+
|
|
195
|
+
### iOS: SF Pro, SF Rounded, and SF Compact
|
|
196
|
+
|
|
197
|
+
San Francisco (SF Pro) is the system typeface on iOS, macOS, and visionOS. It is a variable-weight sans-serif with separate Display (for text above approximately 20pt) and Text (for text at and below 20pt) optical sizes. The Display variant has tighter tracking optimized for large sizes; the Text variant has slightly looser tracking optimized for readability at small sizes. The transition between them happens automatically when using Apple's dynamic text styles — it does not happen automatically for custom font sizes, which is why specifying `UIFont.systemFont(ofSize:)` with sizes above 20pt while in a small-text context will produce tracking that looks subtly wrong.
|
|
198
|
+
|
|
199
|
+
SF Rounded is an alternate variant with softened terminals, appropriate for friendly or playful product tones. SF Mono is the monospaced variant, intended for code display, terminal output, and data values that must align in columns.
|
|
200
|
+
|
|
201
|
+
Dynamic Type is Apple's system for user-controlled text scaling. Users can set their preferred text size in Settings > Accessibility, which scales all text using the Dynamic Type styles up to a maximum multiplier of approximately 3×. Every text style in an iOS app should use a named Dynamic Type style (`UIFont.TextStyle` or SwiftUI's `.font(.body)`, `.font(.headline)`) to participate in this scaling. Never use text below 11pt at any Dynamic Type setting — below 11pt, letters collapse to the point of illegibility even on Retina displays. The minimum label size to target under standard accessibility settings is 13pt for body text, growing to as much as 53pt under the largest accessibility text size.
|
|
202
|
+
|
|
203
|
+
The canonical Dynamic Type scale for iOS, at the default (large) system text size:
|
|
204
|
+
|
|
205
|
+
| Style | Size | Weight | Leading |
|
|
206
|
+
|-------|------|--------|---------|
|
|
207
|
+
| Large Title | 34pt | Regular | 41pt |
|
|
208
|
+
| Title 1 | 28pt | Regular | 34pt |
|
|
209
|
+
| Title 2 | 22pt | Regular | 28pt |
|
|
210
|
+
| Title 3 | 20pt | Regular | 25pt |
|
|
211
|
+
| Headline | 17pt | Semibold | 22pt |
|
|
212
|
+
| Body | 17pt | Regular | 22pt |
|
|
213
|
+
| Callout | 16pt | Regular | 21pt |
|
|
214
|
+
| Subheadline | 15pt | Regular | 20pt |
|
|
215
|
+
| Footnote | 13pt | Regular | 18pt |
|
|
216
|
+
| Caption 1 | 12pt | Regular | 16pt |
|
|
217
|
+
| Caption 2 | 11pt | Regular | 13pt |
|
|
218
|
+
|
|
219
|
+
### Android: Roboto, Noto, and Material 3 Type Scale
|
|
220
|
+
|
|
221
|
+
Roboto is the system typeface on Android. It is a geometric humanist sans-serif designed for screen rendering at varied pixel densities. Noto is the companion family for non-Latin scripts; when a character is not available in Roboto, the system falls back to the appropriate Noto variant. Products targeting global audiences on Android should ensure that their chosen custom typeface has sufficient Unicode coverage, or that their CSS/font stack includes Roboto and Noto as fallbacks for unsupported characters.
|
|
222
|
+
|
|
223
|
+
Material 3 defines a five-category type scale: Display, Headline, Title, Body, and Label, each with three sizes (Large, Medium, Small). Display and Headline are for large, expressive text in hero areas; Title is for component headings and section labels; Body is for paragraph content; Label is for compact UI text in buttons, chips, and captions.
|
|
224
|
+
|
|
225
|
+
| Token | Size | Weight | Line height |
|
|
226
|
+
|-------|------|--------|-------------|
|
|
227
|
+
| Display Large | 57sp | Regular (400) | 64sp |
|
|
228
|
+
| Display Medium | 45sp | Regular | 52sp |
|
|
229
|
+
| Display Small | 36sp | Regular | 44sp |
|
|
230
|
+
| Headline Large | 32sp | Regular | 40sp |
|
|
231
|
+
| Headline Medium | 28sp | Regular | 36sp |
|
|
232
|
+
| Headline Small | 24sp | Regular | 32sp |
|
|
233
|
+
| Title Large | 22sp | Regular | 28sp |
|
|
234
|
+
| Title Medium | 16sp | Medium (500) | 24sp |
|
|
235
|
+
| Title Small | 14sp | Medium | 20sp |
|
|
236
|
+
| Body Large | 16sp | Regular | 24sp |
|
|
237
|
+
| Body Medium | 14sp | Regular | 20sp |
|
|
238
|
+
| Body Small | 12sp | Regular | 16sp |
|
|
239
|
+
| Label Large | 14sp | Medium | 20sp |
|
|
240
|
+
| Label Medium | 12sp | Medium | 16sp |
|
|
241
|
+
| Label Small | 11sp | Medium | 16sp |
|
|
242
|
+
|
|
243
|
+
The `sp` unit (scale-independent pixels) on Android is equivalent to `dp` (density-independent pixels) at default font scale, but scales with the user's font size preference. Always use `sp` for text sizes, never `dp` or `px`, to respect accessibility text scaling preferences.
|
|
244
|
+
|
|
245
|
+
### Web: System Font Stack and Fallback Logic
|
|
246
|
+
|
|
247
|
+
Web typography defaults should reach for the operating system's own UI font before loading a custom typeface. This approach provides the fastest perceived load time (no network request for the font), perfect rendering quality (the OS vendor has tuned the hinting for their own font), and visual consistency with the ambient UI the browser chrome is using.
|
|
248
|
+
|
|
249
|
+
The canonical cross-platform system font stack, in order of preference:
|
|
250
|
+
|
|
251
|
+
```css
|
|
252
|
+
font-family:
|
|
253
|
+
system-ui,
|
|
254
|
+
-apple-system, /* Safari on macOS/iOS pre-system-ui support */
|
|
255
|
+
"Segoe UI", /* Windows 10/11 */
|
|
256
|
+
Roboto, /* Android, Chrome OS */
|
|
257
|
+
"Helvetica Neue", /* Older macOS */
|
|
258
|
+
Arial, /* Universal fallback */
|
|
259
|
+
sans-serif; /* Generic family declaration */
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`system-ui` is the CSS standardized keyword that resolves to the platform UI font. On macOS and iOS it resolves to SF Pro; on Android to Roboto; on Windows 11 to Segoe UI Variable. It is supported in all modern browsers and should be the first declaration in the stack. The `-apple-system` keyword predates `system-ui` standardization and remains useful as a fallback for older Safari versions. The explicit `"Segoe UI"` and `Roboto` declarations serve as fallbacks for contexts where `system-ui` is not supported.
|
|
263
|
+
|
|
264
|
+
When using a custom brand typeface on web, the stack should append the system font stack after the brand font, so that characters not covered by the brand font fall back gracefully rather than to a default serif or monospace.
|
|
265
|
+
|
|
266
|
+
### watchOS: SF Compact
|
|
267
|
+
|
|
268
|
+
watchOS uses SF Compact, a narrower optical variant of San Francisco designed for the physical constraints of a 44mm or 45mm watch face. SF Compact's characters are wider-waisted and more circular than SF Pro, allowing the system to render more characters within the watch's narrow content width while maintaining readability. The guiding constraint for watchOS copy is extreme brevity: labels should be three words or fewer, and preferably fewer. Users glance at the watch for one to two seconds; they do not read sentences. Every watchOS text element should be evaluated by asking whether its meaning can be conveyed in fewer words. If it cannot, the feature may not be appropriate for the watch.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 6. Haptic Feedback
|
|
273
|
+
|
|
274
|
+
Haptics are the tactile confirmation layer of mobile interfaces. They are the difference between an interface that feels alive under the finger and one that feels like touching a pane of glass. Used correctly, haptics confirm actions, communicate state transitions, and orient the user within a physical gesture. Used incorrectly — too frequently, too intensely, or for decorative purposes — they become noise that users disable in Settings, removing an entire feedback channel.
|
|
275
|
+
|
|
276
|
+
### iOS: Taptic Engine
|
|
277
|
+
|
|
278
|
+
Apple's Taptic Engine is the haptic actuator present in all iPhones from iPhone 6s onward. iOS exposes three distinct haptic feedback APIs, each for a different use case.
|
|
279
|
+
|
|
280
|
+
`UIImpactFeedbackGenerator` communicates the physical metaphor of an impact — two objects colliding. It offers three styles: `.light`, `.medium`, and `.heavy`, corresponding to the perceived mass of the collision. Light is appropriate for small UI events like toggles and minor selections; medium for confirmations and modal presentations; heavy for destructive actions and notifications that demand attention. Use this generator when the user's action has a direct, immediate effect and you want to confirm the moment of contact.
|
|
281
|
+
|
|
282
|
+
`UINotificationFeedbackGenerator` communicates the outcome of a completed process. It has three types: `.success`, `.warning`, and `.error`. These should always be paired with their corresponding visual state change — a haptic success without a visible success state is confusing, and a haptic error without a visible error state is alarming without explanation. Do not use notification feedback for routine actions; reserve it for operations with binary outcomes that the user needs to know about.
|
|
283
|
+
|
|
284
|
+
`UISelectionFeedbackGenerator` communicates movement through a series of items — a picker wheel advancing one position, a slider snapping to a value. It produces a subtle rhythmic tick that matches the cadence of physical detents on a mechanical dial. Use it only for continuous selection gestures, not for discrete button taps.
|
|
285
|
+
|
|
286
|
+
The governing rule for iOS haptics is to trigger them from changes the user caused, not from changes the system initiated. Asynchronous events (incoming notifications, background data sync) should not trigger impact or selection haptics; they may use notification haptics only if the outcome is directly relevant to an action the user recently took.
|
|
287
|
+
|
|
288
|
+
### Android: VibrationEffect and HapticFeedbackConstants
|
|
289
|
+
|
|
290
|
+
Android provides haptic feedback through two mechanisms depending on the use case. `HapticFeedbackConstants` is the high-level API accessed through `View.performHapticFeedback()` — it uses semantic constants that the system maps to hardware-appropriate vibration patterns. Relevant constants and their iOS equivalents:
|
|
291
|
+
|
|
292
|
+
| Android constant | iOS equivalent | Semantics |
|
|
293
|
+
|------------------|----------------|-----------|
|
|
294
|
+
| `KEYBOARD_TAP` | `.light` impact | Single character input |
|
|
295
|
+
| `VIRTUAL_KEY` | `.medium` impact | Button press |
|
|
296
|
+
| `LONG_PRESS` | `.medium` impact | Long press activation |
|
|
297
|
+
| `CONFIRM` | `.success` notification | Successful action completion |
|
|
298
|
+
| `REJECT` | `.error` notification | Failed or blocked action |
|
|
299
|
+
| `GESTURE_START` | `.light` impact | Beginning of a drag gesture |
|
|
300
|
+
| `GESTURE_END` | `.medium` impact | Completion of a drag gesture |
|
|
301
|
+
|
|
302
|
+
`VibrationEffect` (accessed via `Vibrator.vibrate(VibrationEffect)`) provides lower-level control for custom patterns, intensities, and compositions. For most application use cases, `HapticFeedbackConstants` is sufficient and preferable — it delegates pattern selection to the platform, which accounts for differences in actuator hardware across Android devices. A pattern tuned for a Pixel's linear resonant actuator will feel wrong on a budget device with an eccentric rotating mass vibrator.
|
|
303
|
+
|
|
304
|
+
Android 12 introduced `VibrationEffect.Composition`, which allows sequencing haptic primitives (ticks, clicks, thuds, spins) with custom durations and amplitudes. This is appropriate for games and rich interactive experiences; for standard application UI, prefer the semantic constants.
|
|
305
|
+
|
|
306
|
+
### Web: navigator.vibrate()
|
|
307
|
+
|
|
308
|
+
The Web Vibration API (`navigator.vibrate(pattern)`) is supported primarily on Android Chrome. iOS Safari does not implement the Vibration API, and desktop browsers ignore it. This severely limits its utility as a universal web haptic strategy — any feature that depends on `navigator.vibrate()` will silently do nothing on half the target audience.
|
|
309
|
+
|
|
310
|
+
The appropriate use of `navigator.vibrate()` on web is limited to a single, clearly defined scenario: **critical confirmations on mobile web experiences where the user is performing an action with significant consequences**, such as confirming a payment or an irreversible deletion. In this narrow case, the haptic provides an additional confirmation signal on devices that support it, while the experience degrades gracefully to visual-only confirmation on devices that do not. Decorative haptics, haptic rhythm patterns, and haptics on every button tap are inappropriate for web — the unreliable cross-device support makes them an inconsistency rather than an enhancement.
|
|
311
|
+
|
|
312
|
+
Before triggering any haptic, always check for API availability:
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
if ('vibrate' in navigator) {
|
|
316
|
+
navigator.vibrate(10); // 10ms — brief confirmation tap
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Never use vibration patterns longer than 20ms for UI feedback; longer patterns feel like alerts rather than confirmations and will concern users who are not expecting a sustained vibration.
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 7. Brand Consistency vs. Platform Convention
|
|
325
|
+
|
|
326
|
+
Every product that ships on multiple platforms faces the same tension: the brand wants visual and behavioral unity across surfaces, while each platform has its own conventions that users expect. Resolving this tension incorrectly in either direction produces problems. Over-platforming — designing each version so differently that the product feels like separate products — creates brand confusion and multiplies design and engineering cost. Over-branding — enforcing visual and behavioral uniformity at the cost of platform conventions — produces products that feel foreign on every platform they ship to.
|
|
327
|
+
|
|
328
|
+
The resolution requires distinguishing between two categories of design decisions: **structural decisions** and **expressive decisions**.
|
|
329
|
+
|
|
330
|
+
Structural decisions define how the user navigates, interacts, and recovers from errors. Navigation patterns, gesture vocabularies, component behaviors, safe area handling, and accessibility features all live in this category. For structural decisions, always follow the platform convention. The cost of deviating is real user confusion — trained reflexes fire and produce the wrong outcome. No brand benefit is worth that cost.
|
|
331
|
+
|
|
332
|
+
Expressive decisions define what the product looks and feels like at a perceptual level. Color palette, typography selection and scale, iconography style, illustration character, motion personality, and copy voice all live in this category. For expressive decisions, always follow the brand. Users recognize the product as "the same product" because these decisions are consistent, not because the tab bar appears at the same Y position on every platform.
|
|
333
|
+
|
|
334
|
+
The practical application is as follows:
|
|
335
|
+
|
|
336
|
+
- Use the correct navigation component for each platform (tab bar on iOS, bottom nav bar on Android) but fill it with the brand's colors, icons, and typography.
|
|
337
|
+
- Use platform-native dialogs and action sheets with the brand's color for accent buttons, not custom-shaped containers that shadow the OS dialog.
|
|
338
|
+
- Never implement a custom gesture that conflicts with an OS-reserved gesture. Design the interaction within the gesture space the platform makes available.
|
|
339
|
+
- Never override platform safe area handling. If a design requires content to appear in an unsafe zone, the design is wrong — not the safe area.
|
|
340
|
+
- Always respect the platform's minimum touch target and accessibility text scaling requirements. These are not platform conventions; they are accessibility requirements, and meeting them is a baseline, not an aspiration.
|
|
341
|
+
|
|
342
|
+
The iOS Human Interface Guidelines, Material Design 3 documentation, and Microsoft Fluent 2 guidelines are the authoritative sources for platform structural decisions. When any detail in this reference conflicts with those sources, those sources take precedence — they are updated continuously and reflect current platform capabilities and requirements. This reference synthesizes those sources for the purposes of the get-design-done framework but does not replace them.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
*This reference governs all platform-targeting decisions within the get-design-done framework. Deviations from platform convention require explicit justification in `.design/DESIGN-CONTEXT.md` as a C-XX constraint, with rationale documented. Cross-references: [iOS HIG](https://developer.apple.com/design/human-interface-guidelines/), [Material Design 3](https://m3.material.io/), [Microsoft Fluent 2](https://fluent2.microsoft.design/).*
|