start-vibing 4.2.0 → 4.3.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/package.json +2 -2
- package/template/.claude/agents/sd-audit.md +167 -4
- package/template/.claude/agents/sd-fix.md +90 -2
- package/template/.claude/agents/sd-research.md +70 -1
- package/template/.claude/skills/mobile-app-patterns/SKILL.md +237 -0
- package/template/.claude/skills/super-design/SKILL.md +27 -9
- package/template/.claude/skills/super-design/references/component-flow-discovery.md +258 -0
- package/template/.claude/skills/super-design/references/design-intelligence-rubric.md +376 -0
- package/template/.claude/skills/super-design/references/design-skills-catalog.md +102 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "start-vibing",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Setup Claude Code with 9 plugins, 6 community skills, and 8 MCP servers. Parallel install, auto-accept, superpowers + ralph-loop.",
|
|
3
|
+
"version": "4.3.0",
|
|
4
|
+
"description": "Setup Claude Code with 9 plugins, 6 community skills, and 8 MCP servers. Parallel install, auto-accept, superpowers + ralph-loop. super-design 0.6: component/flow discovery, 17-category design-intelligence scoring, mobile-native M1-M15 templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"start-vibing": "./dist/cli.js"
|
|
@@ -43,7 +43,12 @@ You are the UX/a11y/perf auditor. You drive the browser DIRECTLY via Playwright
|
|
|
43
43
|
Read in order:
|
|
44
44
|
1. `.claude/skills/super-design/references/audit-methodology.md` — methodology spine
|
|
45
45
|
2. `.claude/skills/super-design/references/playwright-mcp-reference.md` — Playwright MCP API
|
|
46
|
-
3.
|
|
46
|
+
3. `.claude/skills/super-design/references/component-flow-discovery.md` — Step 2.5 orchestration (modals, flows, component states)
|
|
47
|
+
4. `.claude/skills/super-design/references/design-intelligence-rubric.md` — Step 3g 17-category scoring
|
|
48
|
+
5. `.claude/skills/super-design/references/design-skills-catalog.md` — design-skill advisory findings (C16 ≤ 4)
|
|
49
|
+
6. `.claude/skills/mobile-app-patterns/SKILL.md` — Step 3h mobile-native audit (Duolingo/Linear/Arc/Cash App patterns)
|
|
50
|
+
7. `.claude/skills/web-design-guidelines/SKILL.md` — 100+ implicit UX/a11y rules (Vercel Labs)
|
|
51
|
+
8. `docs/super-design/market-analysis.md` — context (archetype, audience, category) + `.cache/evidence/component-comparison.md` for competitor component vocabulary
|
|
47
52
|
|
|
48
53
|
# Non-negotiable rules
|
|
49
54
|
|
|
@@ -91,9 +96,71 @@ session_dir/
|
|
|
91
96
|
├── network/<slug>_<vp>.json
|
|
92
97
|
├── console/<slug>_<vp>.json
|
|
93
98
|
├── vitals/<slug>.json
|
|
94
|
-
|
|
99
|
+
├── axe/<slug>_<vp>.json
|
|
100
|
+
├── interactive/<slug>_<vp>.json # Step 2.5 Phase A
|
|
101
|
+
├── snapshots/<slug>_<vp>_<trigger>_open.yaml # Step 2.5 Phase B
|
|
102
|
+
├── screens/components/<Class>/<state>.png # Step 2.5 Phase D
|
|
103
|
+
├── flows/<flow_name>/step_NN_<action>.png # Step 2.5 Phase C
|
|
104
|
+
├── forms/<formId>_<scenario>.png # Step 2.5 Phase E
|
|
105
|
+
├── component-state-matrix.json # Step 2.5 Phase D
|
|
106
|
+
└── design-intelligence.json # Step 3g
|
|
95
107
|
```
|
|
96
108
|
|
|
109
|
+
## Step 2.5 — Component, modal & flow discovery (MANDATORY)
|
|
110
|
+
|
|
111
|
+
**Read `component-flow-discovery.md` now.** A static page snap tells you ~30% of the
|
|
112
|
+
UI surface. Without Step 2.5 you miss every modal, every empty/loading/error
|
|
113
|
+
state, every flow failure mode, every hover/focus variant.
|
|
114
|
+
|
|
115
|
+
For each (page × viewport) already loaded in Step 2, run all five phases
|
|
116
|
+
sequentially in the SAME browser session (never open new tabs):
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Phase A — Interactive inventory
|
|
120
|
+
browser_evaluate: enumerate every [role=button|link|tab|switch|checkbox|radio],
|
|
121
|
+
[aria-haspopup], [aria-expanded], [data-trigger|data-state], input, select,
|
|
122
|
+
textarea, summary. Classify as navigation | action | trigger | input |
|
|
123
|
+
state-toggle. Save interactive/<slug>_<vp>.json.
|
|
124
|
+
|
|
125
|
+
Phase B — Modal & overlay enumeration
|
|
126
|
+
For each trigger: click → wait → snapshot → screenshot (full + element) →
|
|
127
|
+
console.error? → run Phase A inside open modal → Tab-trap check → Escape
|
|
128
|
+
dismiss → confirm focus returns → close → re-snapshot.
|
|
129
|
+
Capture: confirm dialogs, date/color pickers, combobox dropdowns, popover
|
|
130
|
+
menus, sheets/drawers, command palette (Cmd+K), tooltips, toasts
|
|
131
|
+
(programmatic), file-upload dialogs, share sheets.
|
|
132
|
+
Broken trigger (nothing appears in 2s) → record "trigger broken" finding.
|
|
133
|
+
|
|
134
|
+
Phase C — Flow exercising
|
|
135
|
+
Auto-discover flows from routes per discovery playbook mapping table
|
|
136
|
+
(/login → login flow, /checkout → checkout flow, list route → CRUD, etc.).
|
|
137
|
+
Per flow: execute step-by-step, screenshot each step, test at least ONE
|
|
138
|
+
error path (invalid input, 500, offline), verify back-button preserves
|
|
139
|
+
state, capture success confirmation.
|
|
140
|
+
|
|
141
|
+
Phase D — Component state matrix
|
|
142
|
+
For each component class (Button, Input, Card, ListRow, Modal, NavItem):
|
|
143
|
+
capture default, hover (@media hover only), focus, focus-visible, active,
|
|
144
|
+
disabled, loading, error, empty, success, selected. Save to
|
|
145
|
+
screens/components/<Class>/<state>.png. Missing states → finding.
|
|
146
|
+
Emit component-state-matrix.json.
|
|
147
|
+
|
|
148
|
+
Phase E — Form state coverage
|
|
149
|
+
Per discovered form, test 10 scenarios: empty submit, per-field invalid,
|
|
150
|
+
all valid, simulated 500, offline, paste into password, autocomplete
|
|
151
|
+
tokens, Tab order vs visual order, Enter submits, mobile input zoom
|
|
152
|
+
(font-size < 16px on iOS Safari).
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Budget rule:** On large apps, cap to top 5 triggers per page (ranked by
|
|
156
|
+
proximity to primary CTA), critical flows only (login + checkout + 1 CRUD),
|
|
157
|
+
and the 3 core components (Button, Input, Modal). Record skipped scope in
|
|
158
|
+
`scope.json`.
|
|
159
|
+
|
|
160
|
+
**Hard rules:** ONE Playwright session reused across all phases. Sequential
|
|
161
|
+
only. Every opened modal has open + closed screenshots. Every flow captures
|
|
162
|
+
at least one error path. Broken triggers never abort the audit.
|
|
163
|
+
|
|
97
164
|
## Step 3 — Apply methodology per page × viewport
|
|
98
165
|
|
|
99
166
|
### 3a. Automated a11y
|
|
@@ -114,6 +181,95 @@ Parse `session_dir/vitals/<page>.json`. LCP/INP/CLS/FCP/TTFB/TBT against thresho
|
|
|
114
181
|
### 3f. Implicit criteria (methodology §5)
|
|
115
182
|
60+ checks: empty/loading/error states, focus restoration after modals, aria-live for toasts, password affordances, autocomplete tokens, touch target spacing, deep linking, back-button in SPAs, scroll restoration, copy-paste tolerance, timeout/offline/5xx, session expiration, i18n edges, print stylesheet. pass/fail/n-a with evidence.
|
|
116
183
|
|
|
184
|
+
### 3g. Design-intelligence scoring (MANDATORY)
|
|
185
|
+
|
|
186
|
+
**Read `design-intelligence-rubric.md` now.** WCAG and Nielsen catch accessibility
|
|
187
|
+
and usability failures; they do NOT catch a dashboard that ships 10 oversized
|
|
188
|
+
metric cards stacked in a flex-col. Design intelligence is the implicit
|
|
189
|
+
best-practice layer that a senior design engineer would spot instantly but
|
|
190
|
+
that checklists ignore. This is non-negotiable — absence of this pass is how
|
|
191
|
+
the beats-market mobile dashboard shipped with cards-in-flex-col and nothing
|
|
192
|
+
flagged it.
|
|
193
|
+
|
|
194
|
+
Per page × viewport, score the 17 rubric categories 0–10:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
C1 visual-hierarchy C10 motion-quality
|
|
198
|
+
C2 density C11 navigation-clarity
|
|
199
|
+
C3 consistency-spacing C12 table-on-mobile
|
|
200
|
+
C4 consistency-typography C13 modal-sheet-choice
|
|
201
|
+
C5 consistency-color C14 color-semantics
|
|
202
|
+
C6 whitespace-discipline C15 empty-loading-error-quality
|
|
203
|
+
C7 legibility C16 design-system-coherence
|
|
204
|
+
C8 cta-hierarchy C17 vibecode-smell
|
|
205
|
+
C9 state-feedback
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Formula: `DIS = Σ(score × weight) / Σ(weight) × 10` → 0–100.
|
|
209
|
+
|
|
210
|
+
Bands: 80–100 excellent · 65–79 solid · 50–64 MEDIUM · 35–49 WEAK · <35 broken.
|
|
211
|
+
|
|
212
|
+
Emit `design-intelligence.json` per page:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"page_url": "...",
|
|
217
|
+
"viewport": "mobile",
|
|
218
|
+
"dis_score": 57.5,
|
|
219
|
+
"band": "MEDIUM",
|
|
220
|
+
"categories": {
|
|
221
|
+
"density": { "score": 3, "evidence": "screens/admin_mobile.png", "note": "10 metric cards in flex-col, ~80px each = 800px of scroll for 10 numbers" },
|
|
222
|
+
"design_system_coherence": { "score": 4, "evidence": "...", "recommended_skills": ["typeui-dashboard", "typeui-application"] },
|
|
223
|
+
"...": {}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Any category ≤ 4 spawns a finding** with `rule: design-intelligence-<category>`,
|
|
229
|
+
severity mapped from score (0-1 → sev 4, 2-3 → sev 3, 4 → sev 2), and
|
|
230
|
+
`template_id` from the M-family (see fix-playbook M1-M15).
|
|
231
|
+
|
|
232
|
+
**C16 ≤ 4 MUST emit an advisory finding** citing `design-skills-catalog.md`
|
|
233
|
+
with `recommended_skills: [...]` populated from the selection matrix. This
|
|
234
|
+
is NEVER auto-applied — design-skill adoption is always HIGH risk.
|
|
235
|
+
|
|
236
|
+
### 3h. Mobile-specific audit (viewport ≤ 768px ONLY)
|
|
237
|
+
|
|
238
|
+
**Read `mobile-app-patterns/SKILL.md` now.** Desktop-responsive-down is not
|
|
239
|
+
mobile-native. Run the 21-item checklist verbatim against each mobile page:
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
□ Primary nav is bottom tabs (3-5), not hamburger-only → M1
|
|
243
|
+
□ Dashboards use hero + compact list, not card stack → M2 (cards-in-flex-col)
|
|
244
|
+
□ Tables transformed to card-per-row or compact list → M3 (table-on-mobile)
|
|
245
|
+
□ No input has font-size < 16px → M4 (ios-zoom)
|
|
246
|
+
□ Every interactive target ≥ 44×44 px → M5 (touch-target)
|
|
247
|
+
□ Modals are bottom sheets or full-screen, not centered → M6 (centered-modal)
|
|
248
|
+
□ No hover-only state; every hover has a tap equivalent → M7
|
|
249
|
+
□ Loading states exist for async flows → M8
|
|
250
|
+
□ Empty states exist for zero-data cases → M9
|
|
251
|
+
□ Error states exist for server failures → M10
|
|
252
|
+
□ Safe-area insets respected (iOS notch) → M11
|
|
253
|
+
□ 100svh / 100dvh (not 100vh) for full-height → M12
|
|
254
|
+
□ overscroll-behavior: contain on scroll containers → M13
|
|
255
|
+
□ Pull-to-refresh on primary list views → M14
|
|
256
|
+
□ Swipe actions discoverable (peek on first render) → M15
|
|
257
|
+
□ Back gesture (iOS) works via browser history
|
|
258
|
+
□ Keyboard does not overlap input (visualViewport)
|
|
259
|
+
□ Touch targets 8px+ apart
|
|
260
|
+
□ Long-press fallback for swipe actions
|
|
261
|
+
□ Bottom sheet CTAs sticky above safe area
|
|
262
|
+
□ Content density: 6-8 metrics above the fold (not 2-3)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Each failed item → finding with `rule: mobile-pattern-M<N>`, evidence from
|
|
266
|
+
Step 2.5 artifacts (NOT a fresh snapshot), `template_id: M<N>`.
|
|
267
|
+
|
|
268
|
+
Cross-reference the competitor component vocabulary from
|
|
269
|
+
`.cache/evidence/component-comparison.md` — if every competitor uses bottom
|
|
270
|
+
tabs on mobile and the product uses hamburger-only, density score drops AND
|
|
271
|
+
the M1 finding cites the category norm.
|
|
272
|
+
|
|
117
273
|
## Step 4 — Write findings
|
|
118
274
|
|
|
119
275
|
Append to `docs/super-design/findings/F-NNNN.md` (one file per finding) AND `.super-design/sessions/<id>/findings.json`.
|
|
@@ -125,14 +281,21 @@ Every finding MUST have:
|
|
|
125
281
|
- `snapshot_path` + `snapshot_quote` (verbatim `[ref=eNN]` from YAML)
|
|
126
282
|
- `dom_selector` (resolves)
|
|
127
283
|
- `computed_style_excerpt`
|
|
128
|
-
- `rule` (e.g., color-contrast, label, button-name, nielsen-h7, baymard-checkout-41, cwv-lcp)
|
|
284
|
+
- `rule` (e.g., color-contrast, label, button-name, nielsen-h7, baymard-checkout-41, cwv-lcp, design-intelligence-density, mobile-pattern-M2)
|
|
129
285
|
- `wcag_criterion` (if applicable)
|
|
130
286
|
- `nielsen_heuristic` (if applicable)
|
|
287
|
+
- `dis_category` (if rule is design-intelligence-*: one of the 17 categories)
|
|
131
288
|
- `severity` (0–4 Nielsen)
|
|
132
289
|
- `risk_for_fix` (TRIVIAL | LOW | MEDIUM | HIGH per fix-playbook §12)
|
|
133
|
-
- `suggested_fix` with `template_id` (fix-playbook §7: A1-A15 a11y / V1-V8 design / U1-U10 ux / P1-P10 perf)
|
|
290
|
+
- `suggested_fix` with `template_id` (fix-playbook §7: A1-A15 a11y / V1-V8 design / U1-U10 ux / P1-P10 perf / M1-M15 mobile / DSC-1 design-skill advisory)
|
|
291
|
+
- `recommended_skills` (array, optional — populated for C16 advisories from design-skills-catalog.md selection matrix)
|
|
292
|
+
- `advisory_only` (bool, default false — true for design-skill recommendations and other HIGH-risk aesthetic suggestions that need human sign-off)
|
|
134
293
|
- `finding` — one-sentence impact statement
|
|
135
294
|
|
|
295
|
+
Additionally, write `design-intelligence.json` (per page × viewport) alongside
|
|
296
|
+
findings.json with the full 17-category score breakdown. sd-synthesis reads
|
|
297
|
+
this to produce the executive DIS summary.
|
|
298
|
+
|
|
136
299
|
## Step 5 — Verification snippets
|
|
137
300
|
|
|
138
301
|
### Web Vitals injection
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-fix
|
|
3
|
-
description: Applies surgical fixes for super-design audit findings. Invoked when user explicitly asks for fixes after audit. Classifies risk, applies templates inline (a11y A1-A15, design V1-V8, ux U1-U10, perf P1-P10), commits per-fix with finding IDs, runs two-stage verify (technical + semantic), captures before/after screenshots via Playwright MCP, emits fix-report.md with visual diff, auto-rollback on failure.
|
|
3
|
+
description: Applies surgical fixes for super-design audit findings. Invoked when user explicitly asks for fixes after audit. Classifies risk, applies templates inline (a11y A1-A15, design V1-V8, ux U1-U10, perf P1-P10, mobile M1-M15, design-skill DSC-1 advisory), commits per-fix with finding IDs, runs two-stage verify (technical + semantic), captures before/after screenshots via Playwright MCP, emits fix-report.md with visual diff, auto-rollback on failure.
|
|
4
4
|
tools:
|
|
5
5
|
- Read
|
|
6
6
|
- Edit
|
|
@@ -31,7 +31,13 @@ You are sd-fix — the unified fix agent. You apply templates for all four categ
|
|
|
31
31
|
|
|
32
32
|
# Preflight — always run
|
|
33
33
|
|
|
34
|
-
Read
|
|
34
|
+
Read in order:
|
|
35
|
+
1. `.claude/skills/super-design/references/fix-agent-playbook.md`
|
|
36
|
+
2. `.claude/skills/mobile-app-patterns/SKILL.md` (M-template source — code snippets come from here)
|
|
37
|
+
3. `.claude/skills/super-design/references/design-skills-catalog.md` (DSC-1 advisory selection)
|
|
38
|
+
4. `.claude/skills/super-design/references/design-intelligence-rubric.md` (design-intelligence-* finding context)
|
|
39
|
+
|
|
40
|
+
Then:
|
|
35
41
|
|
|
36
42
|
```bash
|
|
37
43
|
git status --porcelain
|
|
@@ -209,6 +215,85 @@ Source of truth: `references/fix-agent-playbook.md` §7.
|
|
|
209
215
|
- Change form submission semantics → needs_human
|
|
210
216
|
- Introduce new dependency for Undo toast lib → needs_human
|
|
211
217
|
|
|
218
|
+
## mobile templates (M1–M15)
|
|
219
|
+
|
|
220
|
+
Source: `.claude/skills/mobile-app-patterns/SKILL.md` — copy snippets verbatim.
|
|
221
|
+
Apply ONLY when `finding.viewport` is `mobile` (≤768px). Desktop/tablet
|
|
222
|
+
mobile-pattern findings → needs_human (UI architecture decision).
|
|
223
|
+
|
|
224
|
+
| ID | Fix | Risk | Pattern |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| M1 | Hamburger-only nav → `<nav class="fixed inset-x-0 bottom-0 ...">` bottom tab bar (3–5 destinations, fill-icon + label, safe-area-inset-bottom padding) | MEDIUM | needs_human for tab selection |
|
|
227
|
+
| M2 | Metric cards in `flex-col` → `<ul class="divide-y">` compact list rows (py-3 px-4, icon + label on left, tabular-nums value on right). For the hero metric extract into `<section>` with 4xl tabular-nums number + delta chip | LOW | auto when only one metric-card block |
|
|
228
|
+
| M3 | `<table>` at ≤768px → card-per-row (`<article>` with primary text + metadata chips + trailing `[⋯]` menu) OR compact list (avatar + two lines + trailing meta). Preserve sort/filter controls above | MEDIUM | needs_human if >3 columns carry semantic meaning |
|
|
229
|
+
| M4 | Input `font-size < 16px` → `font-size: max(16px, 1rem)` (Tailwind: `text-base` or `text-[max(16px,1rem)]`). Prevents iOS Safari zoom-on-focus | TRIVIAL | auto |
|
|
230
|
+
| M5 | Touch target <44×44 → wrap interactive node in `<button class="size-11 flex items-center justify-center">` keeping inner glyph. Add 8px+ gap to adjacent targets | LOW | auto for isolated buttons |
|
|
231
|
+
| M6 | Centered modal on mobile → migrate to bottom sheet via Vaul/Radix Drawer (`<Drawer.Root>` + `Drawer.Content className="fixed inset-x-0 bottom-0 rounded-t-2xl"`). Full-screen variant for flows | MEDIUM | needs_human — swap affects all call sites |
|
|
232
|
+
| M7 | Hover-only affordance → gate with `@media (hover: hover)`; add tap equivalent (visible button, long-press menu, or always-on chip) | LOW | auto for tooltip-only hovers |
|
|
233
|
+
| M8 | Async action without loading state → apply U2 template (disabled + aria-busy + Spinner + label change + role="status") | TRIVIAL | auto |
|
|
234
|
+
| M9 | Zero-data view without empty state → apply U3 template with mobile-specific illustration+CTA (full-width button) | LOW | auto |
|
|
235
|
+
| M10 | Server failure without error state → apply U4 template; ensure retry button is 44px tall and sticky above safe-area | LOW | auto |
|
|
236
|
+
| M11 | Missing safe-area insets → `padding-top: env(safe-area-inset-top)` on header, `padding-bottom: env(safe-area-inset-bottom)` on bottom nav/CTA. `viewport-fit=cover` in meta viewport | TRIVIAL | auto |
|
|
237
|
+
| M12 | `100vh` anywhere → `100svh` primary, `100dvh` fallback, `-webkit-fill-available` legacy. Replace all occurrences in one file | TRIVIAL | auto |
|
|
238
|
+
| M13 | Inner scroll conflicting with browser pull → `overscroll-behavior: contain` on the inner scroll container | TRIVIAL | auto |
|
|
239
|
+
| M14 | Primary list without pull-to-refresh → propose integration of `react-pull-to-refresh` or Framer gesture; register refresh handler with existing query-key invalidation | MEDIUM | needs_human — new dependency |
|
|
240
|
+
| M15 | Swipe-action row without peek → add `transform: translateX(-8px)` reveal on first render, animate back after 600ms (framer keyframes). Ensure long-press fallback + trailing `[⋯]` menu button | MEDIUM | needs_human if no existing swipe-action library |
|
|
241
|
+
|
|
242
|
+
**Never auto-apply:**
|
|
243
|
+
- Any `M*` fix when finding affects >1 layout component — UI architecture decision
|
|
244
|
+
- Adding a drawer/sheet dependency (Vaul, vaul-drawer) without user confirmation
|
|
245
|
+
- Converting a table to cards when columns drive business logic (sortable compound filters)
|
|
246
|
+
- Replacing existing nav structure — always needs_human
|
|
247
|
+
|
|
248
|
+
## design-skill advisory (DSC-1)
|
|
249
|
+
|
|
250
|
+
Source: `.claude/skills/super-design/references/design-skills-catalog.md`.
|
|
251
|
+
|
|
252
|
+
**This template never writes code.** When audit emits a finding with
|
|
253
|
+
`rule: design-intelligence-design-system-coherence` and score ≤ 4, or with
|
|
254
|
+
`advisory_only: true` and `recommended_skills: [...]`, sd-fix MUST:
|
|
255
|
+
|
|
256
|
+
1. Mark finding `status: proposed` (not applied, not skipped).
|
|
257
|
+
2. Write `.super-design/sessions/<id>/proposals/F-NNNN_design-skill-advisory.md`
|
|
258
|
+
using this structure:
|
|
259
|
+
|
|
260
|
+
```markdown
|
|
261
|
+
# F-NNNN — Design-skill advisory (NON-FIX)
|
|
262
|
+
|
|
263
|
+
**Rule:** design-intelligence-design-system-coherence
|
|
264
|
+
**Risk:** HIGH (aesthetic change requires human sign-off)
|
|
265
|
+
|
|
266
|
+
## Current state
|
|
267
|
+
<embedded finding.screenshot_path + finding.finding one-liner>
|
|
268
|
+
|
|
269
|
+
## Recommended skills
|
|
270
|
+
<for each id in finding.recommended_skills:>
|
|
271
|
+
- **<id>** — <description from design-skills-catalog selection matrix>
|
|
272
|
+
- Visual signature: <catalog signature column>
|
|
273
|
+
- When to recommend: <catalog "When to recommend" column>
|
|
274
|
+
|
|
275
|
+
## Competitor evidence
|
|
276
|
+
<best-matching competitor screenshots from
|
|
277
|
+
.cache/evidence/<slug>/<viewport>/components/ cited as reference — pick
|
|
278
|
+
the 2 closest to the recommended aesthetic>
|
|
279
|
+
|
|
280
|
+
## Next step for the user
|
|
281
|
+
Run `/frontend-design` (or re-run super-design with the chosen skill
|
|
282
|
+
active) to apply this direction. sd-fix cannot auto-apply aesthetic
|
|
283
|
+
realignment because every subsequent fix depends on the chosen
|
|
284
|
+
tokens.
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
3. Append to fix-report.md under a "Proposed aesthetic direction" section,
|
|
288
|
+
NOT under "Applied fixes" — the image diff format is
|
|
289
|
+
`current state ↔ recommended reference` (competitor screenshot), not
|
|
290
|
+
`before ↔ after`.
|
|
291
|
+
|
|
292
|
+
4. No commit. No verify. No after-capture.
|
|
293
|
+
|
|
294
|
+
**DSC-1 is the ONLY finding family where sd-fix writes documentation
|
|
295
|
+
without writing code.**
|
|
296
|
+
|
|
212
297
|
## perf templates (P1–P10)
|
|
213
298
|
|
|
214
299
|
| ID | Fix |
|
|
@@ -245,6 +330,9 @@ Source of truth: `references/fix-agent-playbook.md` §7.
|
|
|
245
330
|
- Never skip Step 5.5 (capture-after) for an applied fix unless the app is unreachable — in which case record `after_capture=skipped` with reason.
|
|
246
331
|
- Never fabricate after-screenshots. No real browser call → no after image.
|
|
247
332
|
- Never run Step 5.5 in parallel against the same browser tab.
|
|
333
|
+
- Never auto-apply DSC-1 (design-skill advisory) — write the proposal, then stop.
|
|
334
|
+
- Never auto-apply any M* fix for desktop/tablet viewports — mobile patterns do not generalize upward.
|
|
335
|
+
- Never introduce a mobile-pattern dependency (Vaul, vaul-drawer, react-pull-to-refresh, react-swipeable-list) without user confirmation.
|
|
248
336
|
|
|
249
337
|
# Evidence rule
|
|
250
338
|
|
|
@@ -24,7 +24,76 @@ Output: exactly one file `docs/super-design/market-analysis.md` + evidence under
|
|
|
24
24
|
|
|
25
25
|
4. **Discover competitors.** 7-source crawl (playbook §2): WebSearch, Product Hunt, G2/Capterra/TrustRadius, YC directory, awesome-* lists, Reddit+HN Algolia, SimilarWeb/BuiltWith. Dedupe by domain. Rank fame × similarity × design-signal. Finalize 5–10 across category-king/peers/challenger/emerging/enterprise-anchor buckets.
|
|
26
26
|
|
|
27
|
-
5. **Audit each competitor via Playwright MCP.** Visit homepage, primary product page, pricing, About. Per playbook §3
|
|
27
|
+
5. **Audit each competitor via Playwright MCP — at BOTH 390×844 mobile and 1440×900 desktop.** Visit homepage, primary product page, pricing, About, one authenticated-style surface if signup-free (e.g., docs, app tour). Per playbook §3 PLUS component-level extraction per §3bis below. Save to `.cache/evidence/<slug>/<viewport>/`.
|
|
28
|
+
|
|
29
|
+
### §3bis. Component-level extraction (mandatory, not optional)
|
|
30
|
+
|
|
31
|
+
A competitor page snap tells us nothing about their UI language. Extract the
|
|
32
|
+
actual design vocabulary. Per competitor, per viewport, capture:
|
|
33
|
+
|
|
34
|
+
| Artifact | How |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `home.png`, `pricing.png`, etc. | Full-page screenshots as before |
|
|
37
|
+
| `components/button_primary.png`, `button_secondary.png`, `button_ghost.png` | `browser_take_screenshot({ element, ref })` cropped to each button variant found on home |
|
|
38
|
+
| `components/nav_desktop.png`, `nav_mobile.png` | Navbar/bottom-tab crops |
|
|
39
|
+
| `components/card_feature.png`, `card_metric.png`, `card_testimonial.png` | Card variant crops |
|
|
40
|
+
| `components/list_row.png` | If any list pattern exists, crop one row |
|
|
41
|
+
| `components/input.png`, `input_focus.png` | Form field default + focused (click into it) |
|
|
42
|
+
| `components/modal.png` | Open newsletter/contact/signup modal if present |
|
|
43
|
+
| `components/empty_state.png` | Navigate to filter-empty or search-no-results if possible |
|
|
44
|
+
| `components/loading.png` | Throttle network in `browser_evaluate` during a nav, capture transient state if possible |
|
|
45
|
+
| `components/footer.png` | Footer crop |
|
|
46
|
+
| `tokens.json` | Computed palette (top 8 colors by frequency), typography (family, sizes, weights used), spacing sample, radius sample, shadow sample |
|
|
47
|
+
| `copy.md` | Hero copy, 3 feature headlines, primary CTA label, testimonial snippet |
|
|
48
|
+
|
|
49
|
+
Save under `.cache/evidence/<slug>/<viewport>/components/`.
|
|
50
|
+
|
|
51
|
+
For each competitor, produce `.cache/evidence/<slug>/component-catalog.md`:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
# <Competitor> — Component Catalog (<viewport>)
|
|
55
|
+
|
|
56
|
+
## Buttons
|
|
57
|
+
- Primary: [image] — background: #FF5733, radius 8px, padding 12px 24px, font-weight 600
|
|
58
|
+
- Secondary: [image] — border + transparent bg
|
|
59
|
+
- Ghost: [image] — text only with hover bg
|
|
60
|
+
|
|
61
|
+
## Navigation
|
|
62
|
+
- Desktop: [image] — fixed top, logo left, nav center, CTA right
|
|
63
|
+
- Mobile: [image] — bottom tabs with 4 destinations + center FAB
|
|
64
|
+
|
|
65
|
+
## Cards
|
|
66
|
+
- Feature: [image]
|
|
67
|
+
- Pricing: [image]
|
|
68
|
+
|
|
69
|
+
## Forms
|
|
70
|
+
- Input default: [image]
|
|
71
|
+
- Input focused: [image]
|
|
72
|
+
|
|
73
|
+
## Modals
|
|
74
|
+
- Signup: [image]
|
|
75
|
+
|
|
76
|
+
## Design tokens observed
|
|
77
|
+
- Palette: #… #… #…
|
|
78
|
+
- Type: Inter 14/16/20/32, weights 400/500/700
|
|
79
|
+
- Spacing: 4/8/16/24/48
|
|
80
|
+
- Radius: 8/12/24
|
|
81
|
+
- Shadows: 0 1px 2px …
|
|
82
|
+
|
|
83
|
+
## Copy tone
|
|
84
|
+
- Hero: "…"
|
|
85
|
+
- CTA: "Start free" (action + value)
|
|
86
|
+
- Tone: confident, direct, technical
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Skip rule:** If a competitor has no interactive elements (static marketing
|
|
90
|
+
site only), mark with `components_available: minimal` and note what is missing.
|
|
91
|
+
Never fabricate.
|
|
92
|
+
|
|
93
|
+
**Category synthesis update:** After all competitors cataloged, also produce
|
|
94
|
+
`.cache/evidence/component-comparison.md` — tabulates every competitor's
|
|
95
|
+
button style, nav style, card style side-by-side. This is the input sd-audit
|
|
96
|
+
and sd-fix use to recommend aesthetic direction.
|
|
28
97
|
|
|
29
98
|
6. **Classify each.** Archetype (§4.1), Aaker peak (§4.2), vibe class, NN/g 4D tone (§7.1), hero-pattern.
|
|
30
99
|
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobile-app-patterns
|
|
3
|
+
description: >
|
|
4
|
+
Best-in-class mobile UI/UX patterns inspired by Duolingo, Linear, Arc, Raycast,
|
|
5
|
+
Notion Mobile, Superhuman. MUST BE USED when designing, auditing, or fixing
|
|
6
|
+
any mobile viewport (≤768px) — especially dashboards, lists, forms, modals,
|
|
7
|
+
nav. Replaces "responsive-web-on-a-phone" thinking with genuine mobile-native
|
|
8
|
+
patterns. Referenced by sd-audit (design-intelligence rubric), sd-fix
|
|
9
|
+
(M-template fixes), and sd-research (component extraction from competitors).
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# mobile-app-patterns
|
|
14
|
+
|
|
15
|
+
## Philosophy
|
|
16
|
+
|
|
17
|
+
A mobile screen is **not** a shrunken desktop. It is a **thumb-reach device** used in 2–10 second sessions with one hand, often while walking/waiting/scrolling. Every pattern here is derived from apps people actually keep on their home screen.
|
|
18
|
+
|
|
19
|
+
## Reference apps (study these before designing)
|
|
20
|
+
|
|
21
|
+
| App | Why | Patterns to extract |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| **Duolingo** | Highest D7 retention in learning category | Compact metric rows, streak flames, XP hero, bottom nav with tab bubbles, full-screen lesson flow, celebration animations |
|
|
24
|
+
| **Linear Mobile** | Fastest feedback SaaS on mobile | Minimal chrome, swipe-to-action on list rows, bottom sheet for create, command-K style quick switcher |
|
|
25
|
+
| **Arc Mobile / Search** | Search-first nav | No bottom tabs — single tap to search/command, gesture stack for back |
|
|
26
|
+
| **Raycast iOS** | Power-user density | Compact list rows with inline metadata, command palette, no decorative chrome |
|
|
27
|
+
| **Notion Mobile** | Heavy content on small screen | Block-based editor, swipe to nest/unnest, floating action button for quick capture |
|
|
28
|
+
| **Superhuman** | Speed as the aesthetic | No loading states visible — optimistic everything, keyboard shortcuts respected on iPad, split-swipe archive/snooze |
|
|
29
|
+
| **Cash App** | Financial density without tables | Big number hero, compact transaction rows (avatar + name + amount + relative time), bottom-sheet send/receive |
|
|
30
|
+
| **Spotify** | Media density | Horizontal scroll rails (not cards in column), sticky now-playing bar, bottom tab nav |
|
|
31
|
+
|
|
32
|
+
## Core mobile patterns
|
|
33
|
+
|
|
34
|
+
### 1. Lists over cards (CRITICAL)
|
|
35
|
+
|
|
36
|
+
**Rule:** On mobile dashboards, `role=listitem` rows beat `role=region` cards for metrics, entities, and history. Cards waste 40–60% of viewport height on padding+radius+shadow for a single data point.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// ANTI-PATTERN (what the beats-market admin dashboard did wrong)
|
|
40
|
+
<div className="flex flex-col gap-3">
|
|
41
|
+
<Card><CardHeader>Total Users</CardHeader><CardContent>16</CardContent></Card>
|
|
42
|
+
<Card><CardHeader>Producers</CardHeader><CardContent>5</CardContent></Card>
|
|
43
|
+
<Card><CardHeader>Orders</CardHeader><CardContent>18</CardContent></Card>
|
|
44
|
+
{/* 10+ cards = endless scroll, no density */}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
// GOOD (Duolingo/Linear/Cash App style)
|
|
48
|
+
<ul className="divide-y divide-border">
|
|
49
|
+
{metrics.map(m => (
|
|
50
|
+
<li key={m.id} className="flex items-center justify-between py-3 px-4">
|
|
51
|
+
<div className="flex items-center gap-3">
|
|
52
|
+
<Icon name={m.icon} className="size-5 text-muted-foreground" />
|
|
53
|
+
<span className="text-sm text-muted-foreground">{m.label}</span>
|
|
54
|
+
</div>
|
|
55
|
+
<span className="text-base font-semibold tabular-nums">{m.value}</span>
|
|
56
|
+
</li>
|
|
57
|
+
))}
|
|
58
|
+
</ul>
|
|
59
|
+
|
|
60
|
+
// EVEN BETTER for a hero metric on mobile (Cash App style)
|
|
61
|
+
<section className="px-4 pt-6 pb-4">
|
|
62
|
+
<p className="text-sm text-muted-foreground">Total revenue</p>
|
|
63
|
+
<h1 className="text-4xl font-bold tabular-nums">R$1.389</h1>
|
|
64
|
+
<p className="text-xs text-muted-foreground mt-1">+12% vs last month</p>
|
|
65
|
+
</section>
|
|
66
|
+
<ul className="divide-y">{/* supporting metrics as compact rows */}</ul>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Density target:** A mobile viewport (390×844) should fit **at least 6–8 metrics above the fold**, not 2–3.
|
|
70
|
+
|
|
71
|
+
### 2. Hero + compact list (dashboard pattern)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
┌─────────────────────────┐
|
|
75
|
+
│ ☰ Dashboard 👤 │ Header (56px fixed)
|
|
76
|
+
├─────────────────────────┤
|
|
77
|
+
│ │
|
|
78
|
+
│ Total Revenue │ HERO: 1 big number
|
|
79
|
+
│ R$ 1,389.00 │ that matters most
|
|
80
|
+
│ +12% this month ↗ │
|
|
81
|
+
│ │
|
|
82
|
+
├─────────────────────────┤
|
|
83
|
+
│ 👥 Users 16 │ Compact metric rows
|
|
84
|
+
│ 🎵 Producers 5 │ (44px each)
|
|
85
|
+
│ 📦 Active Packs 18 │
|
|
86
|
+
│ 🛒 Orders 18 │
|
|
87
|
+
│ 🔄 Refunds 0 │
|
|
88
|
+
│ 📊 Refund Rate 0.0% │
|
|
89
|
+
│ 🛡️ DMCA Claims 0 │
|
|
90
|
+
│ 💬 Open Tickets 1 │
|
|
91
|
+
├─────────────────────────┤
|
|
92
|
+
│ [Home][Metrics][Orders] │ Bottom tab nav (56px)
|
|
93
|
+
└─────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Bottom nav (NOT hamburger) for top-level nav
|
|
97
|
+
|
|
98
|
+
- 3–5 tabs max. More → move to secondary screen via "More" tab.
|
|
99
|
+
- Each tab = a destination, not an action.
|
|
100
|
+
- Fixed position, 56–64px tall, with safe-area inset.
|
|
101
|
+
- Active state: fill icon + label always visible (not hidden).
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<nav className="fixed inset-x-0 bottom-0 z-40 border-t bg-background pb-[env(safe-area-inset-bottom)]">
|
|
105
|
+
<ul className="flex h-14">
|
|
106
|
+
{tabs.map(t => (
|
|
107
|
+
<li key={t.id} className="flex-1">
|
|
108
|
+
<Link
|
|
109
|
+
href={t.href}
|
|
110
|
+
aria-current={active === t.id ? 'page' : undefined}
|
|
111
|
+
className="flex h-full flex-col items-center justify-center gap-1 text-xs"
|
|
112
|
+
>
|
|
113
|
+
<t.Icon className={cn('size-5', active === t.id ? 'fill-current' : '')} />
|
|
114
|
+
<span className={active === t.id ? 'font-semibold' : 'text-muted-foreground'}>{t.label}</span>
|
|
115
|
+
</Link>
|
|
116
|
+
</li>
|
|
117
|
+
))}
|
|
118
|
+
</ul>
|
|
119
|
+
</nav>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Bottom sheets (NOT centered modals) for actions
|
|
123
|
+
|
|
124
|
+
- Centered dialog on mobile = thumb cannot reach top-right close button.
|
|
125
|
+
- Bottom sheet slides up from the bottom, close via drag-down or button at top.
|
|
126
|
+
- Use `<dialog>` or Vaul/Radix + `vaul-drawer` libs.
|
|
127
|
+
|
|
128
|
+
### 5. Full-screen flows (NOT multi-step modals)
|
|
129
|
+
|
|
130
|
+
Onboarding, lesson completion, checkout, create-entity — all should be **full-screen pages** that replace the current view, with a close/back in the top-left, not modal overlays.
|
|
131
|
+
|
|
132
|
+
Duolingo lesson = full-screen. Cash App send = full-screen. Linear create-issue = bottom sheet → expand to full. Never a centered modal trying to cram a form.
|
|
133
|
+
|
|
134
|
+
### 6. Swipe actions on list rows
|
|
135
|
+
|
|
136
|
+
Archive / Delete / Snooze / Complete = left or right swipe on the row. Exposes discoverability via slight peek on first render.
|
|
137
|
+
|
|
138
|
+
Lib: `react-swipeable-list` / custom pointer-events handler. Always provide a long-press or trailing `[…]` button as a11y fallback.
|
|
139
|
+
|
|
140
|
+
### 7. Pull-to-refresh on scrollable lists
|
|
141
|
+
|
|
142
|
+
Native iOS/Android pattern. Every list that fetches server data should implement it. Lib: `react-pull-to-refresh` or Framer Motion gestures.
|
|
143
|
+
|
|
144
|
+
### 8. Typography scale for mobile
|
|
145
|
+
|
|
146
|
+
- Body: **16px** (never smaller — iOS triggers zoom on focus for <16px inputs)
|
|
147
|
+
- Meta / captions: 14px minimum, 13px absolute floor for tabular dense lists
|
|
148
|
+
- Headings: 20/24/32/40 — large hero numbers allowed (44–56px)
|
|
149
|
+
- Line-height: 1.4 body, 1.2 headings, 1.5 long-form reading
|
|
150
|
+
|
|
151
|
+
### 9. Touch targets
|
|
152
|
+
|
|
153
|
+
- **44×44 px minimum** (Apple HIG) or 48dp (Material) — NOT the WCAG 24px floor
|
|
154
|
+
- 8px gap between adjacent targets
|
|
155
|
+
- Full-width list rows: the whole row is the target, not just the text
|
|
156
|
+
|
|
157
|
+
### 10. Data tables → convert on mobile
|
|
158
|
+
|
|
159
|
+
Tables with >3 columns CANNOT fit at 375px. Transform:
|
|
160
|
+
|
|
161
|
+
| Original desktop | Mobile replacement |
|
|
162
|
+
|---|---|
|
|
163
|
+
| Users table (name, email, role, status, date, actions) | List of rows with avatar + primary text + compact metadata stack + trailing `[⋯]` menu |
|
|
164
|
+
| Orders table (id, buyer, items, total, payment, refund, downloads, actions) | Card per order: buyer + total prominent, metadata as chips, CTA row at bottom |
|
|
165
|
+
| Data grid | Virtualized list OR horizontal scroll with sticky first column (only if truly needed) |
|
|
166
|
+
|
|
167
|
+
## Mobile anti-patterns (auto-flag in audits)
|
|
168
|
+
|
|
169
|
+
| Anti-pattern | Why bad | Fix |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| Cards in `flex-col` for metrics | Wastes 40–60% vertical space | Compact list rows with divider |
|
|
172
|
+
| Desktop table <768px | Unreadable microtext or horizontal scroll hell | Card-per-row OR list with primary+meta |
|
|
173
|
+
| Hamburger menu as only nav | Hides primary destinations behind 1+ tap | Bottom tab bar (3–5 tabs) |
|
|
174
|
+
| Centered modal with close in top-right | Unreachable by thumb | Bottom sheet with drag handle |
|
|
175
|
+
| Input `font-size < 16px` | iOS Safari zooms in on focus | Use 16px or `font-size: max(16px, 1rem)` |
|
|
176
|
+
| Fixed header + fixed footer > 25% height | Leaves <75% for content | Collapse header on scroll (framer shrink) |
|
|
177
|
+
| Multi-column layout <600px | Nothing fits | Single column or horizontal rail |
|
|
178
|
+
| Hover-only affordances | Touch has no hover | Gate `@media (hover: hover)` + tap equivalent |
|
|
179
|
+
| Tiny close buttons (<24×24) | Missed taps | 44×44 hit area even if icon is smaller |
|
|
180
|
+
| Toast in top-right | Thumb can't dismiss | Bottom-center toast with swipe-down |
|
|
181
|
+
| 100vh anywhere | iOS Safari URL bar breaks it | `100svh` / `100dvh` with `-webkit-fill-available` fallback |
|
|
182
|
+
| Pull-to-refresh inside inner scroll | Conflicts with browser pull | `overscroll-behavior: contain` |
|
|
183
|
+
|
|
184
|
+
## Competitor reference for mobile patterns by domain
|
|
185
|
+
|
|
186
|
+
| Your app type | Study these on mobile |
|
|
187
|
+
|---|---|
|
|
188
|
+
| Admin / SaaS dashboard | Linear, Height, Plane, Vercel dashboard |
|
|
189
|
+
| Marketplace (buyer) | Instagram Shop, Depop, Vinted, Mercari |
|
|
190
|
+
| Marketplace (seller) | Shopify Mobile, Etsy Seller, Depop |
|
|
191
|
+
| E-commerce checkout | Shop App, Amazon, Stripe Checkout (in a WebView) |
|
|
192
|
+
| Social / community | Discord, Slack, Twitter (X), BlueSky |
|
|
193
|
+
| Learning / habit | Duolingo, Brilliant, Finch, Streaks |
|
|
194
|
+
| Finance / fintech | Cash App, Revolut, Mercury, Ramp |
|
|
195
|
+
| Productivity | Notion, Linear, Raycast, Things 3 |
|
|
196
|
+
| Media | Spotify, Apple Music, YouTube |
|
|
197
|
+
|
|
198
|
+
## How to use this skill
|
|
199
|
+
|
|
200
|
+
- **sd-audit** references these anti-patterns as M-category findings (M1–M12).
|
|
201
|
+
- **sd-fix** applies M-templates with code snippets directly from this skill.
|
|
202
|
+
- **sd-research** studies competitors' mobile viewports against this pattern library, not just home pages.
|
|
203
|
+
- **frontend-design** plugin cross-references this skill when generating mobile UI.
|
|
204
|
+
|
|
205
|
+
## Mandatory mobile audit checklist (≤375px viewport)
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
□ Primary nav is bottom tabs (3-5), not hamburger-only
|
|
209
|
+
□ Dashboards use hero + compact list, not card stack
|
|
210
|
+
□ Tables transformed to card-per-row or compact list
|
|
211
|
+
□ No input has font-size < 16px
|
|
212
|
+
□ Every interactive target ≥ 44×44 px
|
|
213
|
+
□ Modals are bottom sheets or full-screen, not centered
|
|
214
|
+
□ No hover-only state; every hover has a tap equivalent
|
|
215
|
+
□ Loading states exist for async flows
|
|
216
|
+
□ Empty states exist for zero-data cases
|
|
217
|
+
□ Error states exist for server failures
|
|
218
|
+
□ Safe-area insets respected (iOS notch, home indicator)
|
|
219
|
+
□ Text uses 100svh / 100dvh (not 100vh) for full-height
|
|
220
|
+
□ Scroll containers use overscroll-behavior: contain
|
|
221
|
+
□ Pull-to-refresh implemented on primary list views
|
|
222
|
+
□ Swipe actions discoverable (peek on first render)
|
|
223
|
+
□ Back gesture (iOS) works via browser history
|
|
224
|
+
□ Keyboard does not overlap input (visualViewport API)
|
|
225
|
+
□ Touch targets 8px+ apart
|
|
226
|
+
□ Long-press fallback for swipe actions
|
|
227
|
+
□ Bottom sheet CTAs sticky above safe area
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## References
|
|
231
|
+
|
|
232
|
+
- Linear Method — https://linear.app/method
|
|
233
|
+
- Vercel Design Engineering — https://vercel.com/blog/design-engineering-at-vercel
|
|
234
|
+
- iOS HIG Touch Targets — https://developer.apple.com/design/human-interface-guidelines/layout
|
|
235
|
+
- Material 3 Bottom App Bar — https://m3.material.io/components/bottom-app-bar/overview
|
|
236
|
+
- NN/g Mobile UX — https://www.nngroup.com/topic/mobile-and-tablet-design/
|
|
237
|
+
- Baymard Mobile Checkout — https://baymard.com/checkout-usability
|