@hegemonart/get-design-done 1.0.7
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 +63 -0
- package/.claude-plugin/plugin.json +54 -0
- package/CHANGELOG.md +221 -0
- package/LICENSE +21 -0
- package/README.md +724 -0
- package/SKILL.md +232 -0
- package/agents/README.md +226 -0
- package/agents/a11y-mapper.md +118 -0
- package/agents/component-taxonomy-mapper.md +88 -0
- package/agents/design-advisor.md +139 -0
- package/agents/design-assumptions-analyzer.md +171 -0
- package/agents/design-auditor.md +383 -0
- package/agents/design-context-builder.md +544 -0
- package/agents/design-context-checker-gate.md +90 -0
- package/agents/design-context-checker.md +260 -0
- package/agents/design-discussant.md +98 -0
- package/agents/design-doc-writer.md +229 -0
- package/agents/design-executor.md +452 -0
- package/agents/design-figma-writer.md +302 -0
- package/agents/design-fixer.md +180 -0
- package/agents/design-integration-checker-gate.md +93 -0
- package/agents/design-integration-checker.md +326 -0
- package/agents/design-pattern-mapper.md +206 -0
- package/agents/design-phase-researcher.md +229 -0
- package/agents/design-plan-checker.md +164 -0
- package/agents/design-planner.md +352 -0
- package/agents/design-reflector.md +175 -0
- package/agents/design-research-synthesizer.md +127 -0
- package/agents/design-verifier-gate.md +97 -0
- package/agents/design-verifier.md +605 -0
- package/agents/gdd-graphify-sync.md +100 -0
- package/agents/gdd-intel-updater.md +88 -0
- package/agents/gdd-learnings-extractor.md +85 -0
- package/agents/motion-mapper.md +103 -0
- package/agents/token-mapper.md +103 -0
- package/agents/visual-hierarchy-mapper.md +95 -0
- package/connections/chromatic.md +247 -0
- package/connections/claude-design.md +190 -0
- package/connections/connections.md +218 -0
- package/connections/figma-writer.md +139 -0
- package/connections/figma.md +146 -0
- package/connections/graphify.md +197 -0
- package/connections/pinterest.md +153 -0
- package/connections/preview.md +173 -0
- package/connections/refero.md +189 -0
- package/connections/storybook.md +280 -0
- package/hooks/budget-enforcer.js +318 -0
- package/hooks/context-exhaustion.js +127 -0
- package/hooks/gdd-read-injection-scanner.js +44 -0
- package/hooks/hooks.json +44 -0
- package/package.json +60 -0
- package/reference/BRANCH-PROTECTION.md +65 -0
- package/reference/DEPRECATIONS.md +41 -0
- package/reference/STATE-TEMPLATE.md +200 -0
- package/reference/accessibility.md +190 -0
- package/reference/anti-patterns.md +336 -0
- package/reference/audit-scoring.md +205 -0
- package/reference/checklists.md +137 -0
- package/reference/config-schema.md +319 -0
- package/reference/debugger-philosophy.md +32 -0
- package/reference/heuristics.md +201 -0
- package/reference/intel-schema.md +266 -0
- package/reference/model-prices.md +37 -0
- package/reference/model-tiers.md +118 -0
- package/reference/motion.md +285 -0
- package/reference/parallelism-rules.md +108 -0
- package/reference/priority-matrix.md +31 -0
- package/reference/project-skills-guide.md +42 -0
- package/reference/review-format.md +107 -0
- package/reference/schemas/config.schema.json +41 -0
- package/reference/schemas/hooks.schema.json +55 -0
- package/reference/schemas/intel.schema.json +191 -0
- package/reference/schemas/marketplace.schema.json +72 -0
- package/reference/schemas/plugin.schema.json +59 -0
- package/reference/shared-preamble.md +82 -0
- package/reference/typography.md +229 -0
- package/scripts/aggregate-agent-metrics.js +144 -0
- package/scripts/apply-branch-protection.sh +75 -0
- package/scripts/bootstrap-manifest.txt +3 -0
- package/scripts/bootstrap.sh +80 -0
- package/scripts/build-intel.cjs +458 -0
- package/scripts/detect-stale-refs.cjs +101 -0
- package/scripts/extract-changelog-section.cjs +57 -0
- package/scripts/release-smoke-test.cjs +169 -0
- package/scripts/rollback-release.sh +42 -0
- package/scripts/run-injection-scanner-ci.cjs +92 -0
- package/scripts/validate-frontmatter.cjs +68 -0
- package/scripts/validate-schemas.cjs +225 -0
- package/scripts/verify-version-sync.cjs +30 -0
- package/skills/add-backlog/SKILL.md +47 -0
- package/skills/analyze-dependencies/SKILL.md +184 -0
- package/skills/apply-reflections/SKILL.md +112 -0
- package/skills/audit/SKILL.md +54 -0
- package/skills/brief/SKILL.md +75 -0
- package/skills/cache-manager/SKILL.md +120 -0
- package/skills/compare/SKILL.md +322 -0
- package/skills/complete-cycle/SKILL.md +33 -0
- package/skills/darkmode/SKILL.md +331 -0
- package/skills/debug/SKILL.md +38 -0
- package/skills/design/SKILL.md +281 -0
- package/skills/discover/SKILL.md +172 -0
- package/skills/discuss/SKILL.md +67 -0
- package/skills/do/SKILL.md +45 -0
- package/skills/explore/SKILL.md +109 -0
- package/skills/extract-learnings/SKILL.md +98 -0
- package/skills/fast/SKILL.md +44 -0
- package/skills/figma-write/SKILL.md +40 -0
- package/skills/graphify/SKILL.md +48 -0
- package/skills/health/SKILL.md +48 -0
- package/skills/help/SKILL.md +76 -0
- package/skills/list-assumptions/SKILL.md +60 -0
- package/skills/map/SKILL.md +112 -0
- package/skills/new-cycle/SKILL.md +35 -0
- package/skills/new-project/SKILL.md +53 -0
- package/skills/next/SKILL.md +42 -0
- package/skills/note/SKILL.md +47 -0
- package/skills/optimize/SKILL.md +120 -0
- package/skills/pause/SKILL.md +41 -0
- package/skills/plan/SKILL.md +251 -0
- package/skills/plant-seed/SKILL.md +47 -0
- package/skills/pr-branch/SKILL.md +31 -0
- package/skills/progress/SKILL.md +60 -0
- package/skills/quick/SKILL.md +43 -0
- package/skills/reapply-patches/SKILL.md +31 -0
- package/skills/reflect/SKILL.md +73 -0
- package/skills/resume/SKILL.md +37 -0
- package/skills/review-backlog/SKILL.md +45 -0
- package/skills/router/SKILL.md +67 -0
- package/skills/scan/SKILL.md +721 -0
- package/skills/settings/SKILL.md +78 -0
- package/skills/ship/SKILL.md +31 -0
- package/skills/sketch/SKILL.md +78 -0
- package/skills/sketch-wrap-up/SKILL.md +88 -0
- package/skills/skill-manifest/SKILL.md +79 -0
- package/skills/spike/SKILL.md +67 -0
- package/skills/spike-wrap-up/SKILL.md +81 -0
- package/skills/stats/SKILL.md +50 -0
- package/skills/style/SKILL.md +193 -0
- package/skills/synthesize/SKILL.md +93 -0
- package/skills/todo/SKILL.md +54 -0
- package/skills/undo/SKILL.md +30 -0
- package/skills/update/SKILL.md +36 -0
- package/skills/verify/SKILL.md +452 -0
- package/skills/warm-cache/SKILL.md +113 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Deprecations
|
|
2
|
+
|
|
3
|
+
This registry tracks renamed, split, or removed plugin concepts. Each entry names the deprecated name, the phase that deprecated it, the replacement, and a migration note.
|
|
4
|
+
|
|
5
|
+
**CI enforcement:** `scripts/detect-stale-refs.cjs` scans shipped `.md` files
|
|
6
|
+
for legacy tokens and fails the build on any occurrence. The scanner's pattern
|
|
7
|
+
list mirrors the tokens named below. When a new deprecation lands here, update
|
|
8
|
+
the scanner pattern list in lockstep.
|
|
9
|
+
|
|
10
|
+
## Namespaces
|
|
11
|
+
|
|
12
|
+
- **`/design:<cmd>`** → `/gdd:<cmd>` — deprecated in Phase 7 (namespace rename). All commands now use the `/gdd:` prefix. Migrated: every shipped skill invocation and agent reference now uses `/gdd:`.
|
|
13
|
+
|
|
14
|
+
## Agents
|
|
15
|
+
|
|
16
|
+
- **`design-context-builder`** — replaced by the Phase 3 agent split (design-context-reader + design-context-summarizer). Mentioned only in historical documentation; new work must spawn the split agents directly.
|
|
17
|
+
- **`design-pattern-mapper`** (monolithic) → split into 5 domain mappers in Phase 3 (migrated):
|
|
18
|
+
- `token-mapper`
|
|
19
|
+
- `component-taxonomy-mapper`
|
|
20
|
+
- `a11y-mapper`
|
|
21
|
+
- `motion-mapper`
|
|
22
|
+
- `visual-hierarchy-mapper`
|
|
23
|
+
|
|
24
|
+
The legacy `design-pattern-mapper.md` agent is retained as a compatibility shim pending full removal in a later phase. New work should spawn the domain mappers directly.
|
|
25
|
+
|
|
26
|
+
## Stages
|
|
27
|
+
|
|
28
|
+
- **`scan`** (stage name) → merged/renamed into `explore` in Phase 3. Migration: references to the `scan` stage in shipped skills and agents were replaced with `explore`.
|
|
29
|
+
- **`discover`** (stage name) → merged/renamed into `explore` in Phase 3. Migration: references to the `discover` stage in shipped skills and agents were replaced with `explore`.
|
|
30
|
+
|
|
31
|
+
## Scanner scope
|
|
32
|
+
|
|
33
|
+
`scripts/detect-stale-refs.cjs` flags these tokens (line-granular match):
|
|
34
|
+
|
|
35
|
+
- `/design:<cmd>` — any occurrence of the legacy namespace
|
|
36
|
+
- `design-context-builder` (standalone word)
|
|
37
|
+
- `design-pattern-mapper` (when not followed by `-<suffix>`)
|
|
38
|
+
- `scan/SKILL.md` and `discover/SKILL.md` path references
|
|
39
|
+
|
|
40
|
+
The scanner excludes `.planning/`, `.claude/`, `.design/`, `node_modules/`,
|
|
41
|
+
`test-fixture/`, and this file itself.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# `.design/STATE.md` Template
|
|
2
|
+
|
|
3
|
+
This is the canonical template for the design pipeline's runtime state file.
|
|
4
|
+
|
|
5
|
+
**How stages use this template:**
|
|
6
|
+
- At scan stage entry, if `.design/STATE.md` does not exist, scan copies this template to `.design/STATE.md` and fills the frontmatter `started_at` and `last_checkpoint` with the current ISO 8601 timestamp.
|
|
7
|
+
- Every subsequent stage (discover, plan, design, verify) reads `.design/STATE.md` at entry and updates it at completion, per the Write Contract below.
|
|
8
|
+
- `.design/` is gitignored (not distributed with the plugin); only this template ships.
|
|
9
|
+
|
|
10
|
+
**Distinction from `.planning/STATE.md`:**
|
|
11
|
+
- `.planning/STATE.md` is GSD development state — used by the developers building this plugin.
|
|
12
|
+
- `.design/STATE.md` is pipeline runtime state — used by the pipeline when it runs in a user's project.
|
|
13
|
+
- Keep them strictly separate. Cross-references between them are deferred to Phase 6 per CONTEXT.md.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Template body
|
|
18
|
+
|
|
19
|
+
Copy the block below (between the `==== BEGIN TEMPLATE ====` and `==== END TEMPLATE ====` markers) to `.design/STATE.md` at scan entry.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
==== BEGIN TEMPLATE ====
|
|
23
|
+
---
|
|
24
|
+
pipeline_state_version: 1.0
|
|
25
|
+
stage: brief
|
|
26
|
+
cycle: ""
|
|
27
|
+
wave: 1
|
|
28
|
+
started_at: <ISO 8601 timestamp — set once at scan entry>
|
|
29
|
+
last_checkpoint: <ISO 8601 timestamp — updated at each stage exit>
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Pipeline State — <project name>
|
|
33
|
+
|
|
34
|
+
<position>
|
|
35
|
+
stage: brief
|
|
36
|
+
wave: 1
|
|
37
|
+
task_progress: 0/0
|
|
38
|
+
status: initialized
|
|
39
|
+
handoff_source: ""
|
|
40
|
+
handoff_path: ""
|
|
41
|
+
skipped_stages: ""
|
|
42
|
+
</position>
|
|
43
|
+
<!-- handoff_source: "claude-design-html" | "claude-design-bundle" | "manual" | "" (empty = normal pipeline) -->
|
|
44
|
+
<!-- handoff_path: path to the handoff bundle file or directory; empty for normal pipeline runs -->
|
|
45
|
+
<!-- skipped_stages: comma-separated list of stages bypassed by handoff routing (e.g., "scan, discover, plan") -->
|
|
46
|
+
|
|
47
|
+
<decisions>
|
|
48
|
+
<!-- Filled by discover stage. Format: -->
|
|
49
|
+
<!-- D-01: [decision text] (locked | tentative) -->
|
|
50
|
+
</decisions>
|
|
51
|
+
|
|
52
|
+
<must_haves>
|
|
53
|
+
<!-- Filled by discover stage. Format: -->
|
|
54
|
+
<!-- M-01: [observable behavior description] | status: pending -->
|
|
55
|
+
<!-- Valid status values: pending | pass | fail -->
|
|
56
|
+
</must_haves>
|
|
57
|
+
|
|
58
|
+
<connections>
|
|
59
|
+
<!-- Detected at scan entry; updated if connections become available mid-pipeline. -->
|
|
60
|
+
<!-- Format: <connection_name>: <available | unavailable | not_configured> -->
|
|
61
|
+
figma: not_configured
|
|
62
|
+
refero: not_configured
|
|
63
|
+
pinterest: not_configured
|
|
64
|
+
claude_design: not_configured
|
|
65
|
+
</connections>
|
|
66
|
+
|
|
67
|
+
<blockers>
|
|
68
|
+
<!-- Active blockers preventing stage completion. -->
|
|
69
|
+
<!-- Format: [stage] [ISO date]: [description] -->
|
|
70
|
+
</blockers>
|
|
71
|
+
|
|
72
|
+
<parallelism_decision>
|
|
73
|
+
<!-- Written by each stage orchestrator after computing parallelism verdict -->
|
|
74
|
+
<!-- Format:
|
|
75
|
+
stage: explore
|
|
76
|
+
verdict: parallel | serial
|
|
77
|
+
reason: "2 mappers, disjoint Touches, savings est. 45s"
|
|
78
|
+
agents: ["token-mapper", "component-taxonomy-mapper"]
|
|
79
|
+
-->
|
|
80
|
+
</parallelism_decision>
|
|
81
|
+
|
|
82
|
+
<todos>
|
|
83
|
+
<!-- Mirror of .design/TODO.md counts for quick lookup by /gdd:progress and /gdd:stats. -->
|
|
84
|
+
<!-- Format:
|
|
85
|
+
pending: 0
|
|
86
|
+
in_progress: 0
|
|
87
|
+
done: 0
|
|
88
|
+
-->
|
|
89
|
+
</todos>
|
|
90
|
+
|
|
91
|
+
<timestamps>
|
|
92
|
+
started_at: <ISO 8601>
|
|
93
|
+
last_checkpoint: <ISO 8601>
|
|
94
|
+
brief_completed_at: ~
|
|
95
|
+
explore_completed_at: ~
|
|
96
|
+
plan_completed_at: ~
|
|
97
|
+
design_completed_at: ~
|
|
98
|
+
verify_completed_at: ~
|
|
99
|
+
</timestamps>
|
|
100
|
+
==== END TEMPLATE ====
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Field reference
|
|
106
|
+
|
|
107
|
+
### Frontmatter
|
|
108
|
+
|
|
109
|
+
| Field | Type | Set by | Purpose |
|
|
110
|
+
|-------|------|--------|---------|
|
|
111
|
+
| `pipeline_state_version` | float | fixed at `1.0` | Forward-compat marker for future format changes |
|
|
112
|
+
| `stage` | enum | every stage at entry | Current stage — one of: `brief|explore|plan|design|verify` |
|
|
113
|
+
| `cycle` | string | lifecycle commands | Cycle identifier for Wave B multi-cycle projects (default: empty string) |
|
|
114
|
+
| `wave` | int | every stage | Wave number within current stage |
|
|
115
|
+
| `started_at` | ISO 8601 | scan at creation | Immutable — never updated after creation |
|
|
116
|
+
| `last_checkpoint` | ISO 8601 | every stage at exit | Updated on every stage transition and on mid-stage checkpoint |
|
|
117
|
+
|
|
118
|
+
### `<position>`
|
|
119
|
+
|
|
120
|
+
Mirrors frontmatter stage/wave plus progress and status. Duplication is intentional — frontmatter is scannable by tooling; `<position>` is scannable by prose reading.
|
|
121
|
+
|
|
122
|
+
- `task_progress`: `<completed>/<total>` — e.g. `3/7` means 3 of 7 tasks in the current stage complete
|
|
123
|
+
- `status`: one of
|
|
124
|
+
- `initialized` — scan just created the file, no work done
|
|
125
|
+
- `in_progress` — stage is actively running
|
|
126
|
+
- `completed` — stage finished successfully; next stage may begin
|
|
127
|
+
- `blocked` — stage cannot proceed; see `<blockers>`
|
|
128
|
+
|
|
129
|
+
### `<decisions>`
|
|
130
|
+
|
|
131
|
+
Discover stage populates. Each decision:
|
|
132
|
+
- `D-<NN>`: sequential identifier
|
|
133
|
+
- `[decision text]`: human-readable statement
|
|
134
|
+
- `(locked | tentative)`: `locked` means downstream stages must honor; `tentative` means open for revision by subsequent stages
|
|
135
|
+
|
|
136
|
+
### `<must_haves>`
|
|
137
|
+
|
|
138
|
+
Discover stage populates with observable behaviors. Verify stage updates status.
|
|
139
|
+
- `M-<NN>`: sequential identifier
|
|
140
|
+
- `[description]`: testable behavior or artifact
|
|
141
|
+
- `status`: `pending` (default), `pass` (verify confirmed), `fail` (verify rejected)
|
|
142
|
+
|
|
143
|
+
### `<connections>`
|
|
144
|
+
|
|
145
|
+
One line per external connection. Detected at scan entry via MCP availability probes.
|
|
146
|
+
- `available`: MCP tool present and responding
|
|
147
|
+
- `unavailable`: MCP configured but not responding (auth failure, offline, etc.)
|
|
148
|
+
- `not_configured`: MCP not present in session
|
|
149
|
+
|
|
150
|
+
### `<blockers>`
|
|
151
|
+
|
|
152
|
+
Append-only log of active blockers. Format: `[stage] [ISO date]: [description]`. Cleared manually when blocker resolves (do not auto-clear — preserve the record).
|
|
153
|
+
|
|
154
|
+
### `<timestamps>`
|
|
155
|
+
|
|
156
|
+
Per-stage completion record. `~` means not yet completed. Updated at each stage's successful exit.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Write Contract
|
|
161
|
+
|
|
162
|
+
Every stage that runs in the pipeline MUST follow this contract when reading and writing `.design/STATE.md`:
|
|
163
|
+
|
|
164
|
+
**At entry:**
|
|
165
|
+
1. Read `.design/STATE.md`. If the file does not exist and the current stage is `scan`, create it from this template with `started_at` = now and `last_checkpoint` = now; otherwise abort with a clear error ("run scan first").
|
|
166
|
+
2. Parse frontmatter `stage` and `<position>` `status`.
|
|
167
|
+
3. If `stage == current_stage` and `status == in_progress`: RESUME — pick up from `task_progress` offset; do not reset progress.
|
|
168
|
+
4. If `stage != current_stage`: this is a normal stage transition. Set frontmatter `stage = current_stage`, `<position>` `stage = current_stage`, `<position>` `status = in_progress`, `<position>` `task_progress = 0/<total>`.
|
|
169
|
+
5. Update `<connections>` by probing each MCP tool; write the detected status.
|
|
170
|
+
6. Update `last_checkpoint` to now.
|
|
171
|
+
7. Write `.design/STATE.md`.
|
|
172
|
+
|
|
173
|
+
**During execution (mid-stage checkpoints):**
|
|
174
|
+
- After each task completes, update `<position>` `task_progress` and `last_checkpoint`. Write `.design/STATE.md`.
|
|
175
|
+
- This enables resume if the stage is interrupted.
|
|
176
|
+
|
|
177
|
+
**At exit (successful completion):**
|
|
178
|
+
1. Set `<position>` `status = completed`.
|
|
179
|
+
2. Set the corresponding `<stage>_completed_at` timestamp in `<timestamps>`.
|
|
180
|
+
3. Update `last_checkpoint`.
|
|
181
|
+
4. Write `.design/STATE.md`.
|
|
182
|
+
|
|
183
|
+
**At exit (blocked):**
|
|
184
|
+
1. Set `<position>` `status = blocked`.
|
|
185
|
+
2. Append to `<blockers>`: `[<stage>] [<ISO date>]: <blocker description>`.
|
|
186
|
+
3. Update `last_checkpoint`.
|
|
187
|
+
4. Write `.design/STATE.md`.
|
|
188
|
+
|
|
189
|
+
**Resume semantics (STATE-03):**
|
|
190
|
+
- A stage re-invoked with `status == in_progress` and `stage == self` must resume from `task_progress` without re-running completed tasks.
|
|
191
|
+
- The `task_progress` numerator is the ONLY source of truth for resume. Consumers must NOT infer resume point from timestamps alone.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Notes for Phase 2 implementors
|
|
196
|
+
|
|
197
|
+
- Do not add new top-level XML sections without updating this template.
|
|
198
|
+
- The write contract is non-negotiable — stages that skip the read-at-entry step break resume.
|
|
199
|
+
- `<decisions>` and `<must_haves>` identifiers are sequential per-project, not globally unique. A new pipeline run on the same project starts at `D-01` / `M-01`.
|
|
200
|
+
- When in doubt, prefer appending new fields to existing sections over introducing new sections — preserves compatibility with `pipeline_state_version: 1.0`.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Accessibility — Thresholds and Requirements
|
|
2
|
+
|
|
3
|
+
These are concrete, measurable standards. WCAG 2.1 AA is the minimum baseline for all design work unless the client explicitly requires AAA or specifies otherwise.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## WCAG 2.1 AA — Required Thresholds
|
|
8
|
+
|
|
9
|
+
### Color Contrast
|
|
10
|
+
|
|
11
|
+
| Text type | Minimum ratio (AA) | Enhanced (AAA) |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Normal text (< 18pt / < 14pt bold) | **4.5 : 1** | 7 : 1 |
|
|
14
|
+
| Large text (≥ 18pt or ≥ 14pt bold) | **3 : 1** | 4.5 : 1 |
|
|
15
|
+
| UI components and graphical objects | **3 : 1** | — |
|
|
16
|
+
| Decorative elements | No requirement | — |
|
|
17
|
+
|
|
18
|
+
**Calculate contrast**: `(L1 + 0.05) / (L2 + 0.05)` where L1 is the lighter luminance.
|
|
19
|
+
|
|
20
|
+
Common pitfalls:
|
|
21
|
+
- Placeholder text in inputs: must meet 4.5:1 (often doesn't — gray placeholders fail)
|
|
22
|
+
- Disabled state text: WCAG exempts disabled elements, but aim for ≥ 3:1 anyway
|
|
23
|
+
- Link color vs body text: must be distinguishable by more than color alone (underline or 3:1 ratio vs background)
|
|
24
|
+
- Focus ring color vs its background: must meet 3:1
|
|
25
|
+
|
|
26
|
+
Tools: Use browser DevTools > Accessibility tab, or pass hex values through contrast calculation.
|
|
27
|
+
|
|
28
|
+
### Touch Target Size
|
|
29
|
+
|
|
30
|
+
| Platform | Minimum tap target |
|
|
31
|
+
|---|---|
|
|
32
|
+
| iOS (Apple HIG) | **44 × 44 pt** |
|
|
33
|
+
| Android (Material Design) | **48 × 48 dp** |
|
|
34
|
+
| Web (WCAG 2.5.5 AAA) | **44 × 44 px** |
|
|
35
|
+
| Web (WCAG 2.5.8 AA — WCAG 2.2) | **24 × 24 px** (minimum, with spacing) |
|
|
36
|
+
|
|
37
|
+
Recommended target: 44 × 44 px on all platforms. Never smaller for primary actions.
|
|
38
|
+
|
|
39
|
+
Minimum spacing between targets: **8px** to prevent accidental taps.
|
|
40
|
+
|
|
41
|
+
Use `hitSlop` in React Native to expand tap area beyond visual bounds:
|
|
42
|
+
```js
|
|
43
|
+
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Focus States
|
|
47
|
+
|
|
48
|
+
All interactive elements must have a visible focus indicator.
|
|
49
|
+
|
|
50
|
+
**Required for WCAG 2.4.11 (AA — WCAG 2.2):**
|
|
51
|
+
- Focus indicator at minimum: **2px solid** outline, encloses the component
|
|
52
|
+
- Contrast between focused and unfocused: **3:1**
|
|
53
|
+
- Focus indicator doesn't overlap component content
|
|
54
|
+
|
|
55
|
+
**Best practice:**
|
|
56
|
+
```css
|
|
57
|
+
:focus-visible {
|
|
58
|
+
outline: 2px solid var(--color-focus-ring);
|
|
59
|
+
outline-offset: 2px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Never remove focus without replacement */
|
|
63
|
+
:focus:not(:focus-visible) {
|
|
64
|
+
outline: none; /* OK — only removes keyboard focus ring for mouse users */
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Recommended focus ring: **3px solid**, `2px offset`, brand primary or `#2563eb`.
|
|
69
|
+
|
|
70
|
+
### Semantic Structure
|
|
71
|
+
|
|
72
|
+
- One `<h1>` per page. Headings are sequential: `h1` → `h2` → `h3` — never skip levels.
|
|
73
|
+
- Interactive elements are focusable: use `<button>` for buttons, `<a href>` for links — never `<div onClick>`.
|
|
74
|
+
- Form inputs have associated `<label for="id">` — not just placeholder text.
|
|
75
|
+
- Images have descriptive `alt=""` for meaningful images; `alt=""` for decorative.
|
|
76
|
+
- Icon-only buttons have `aria-label`: `<button aria-label="Close dialog">×</button>`.
|
|
77
|
+
|
|
78
|
+
### Color Must Not Be The Only Differentiator
|
|
79
|
+
|
|
80
|
+
Error states: red color + error icon + text message (not just red border).
|
|
81
|
+
Required fields: asterisk (*) + visible label (not just red label).
|
|
82
|
+
Charts: color + pattern/texture + direct labels.
|
|
83
|
+
|
|
84
|
+
### Keyboard Navigation
|
|
85
|
+
|
|
86
|
+
All functionality reachable via keyboard:
|
|
87
|
+
- Tab order matches visual reading order (top-left → bottom-right)
|
|
88
|
+
- Focus never trapped except in modals (where it SHOULD be trapped)
|
|
89
|
+
- `Escape` closes any overlay (modal, dropdown, drawer)
|
|
90
|
+
- Enter/Space activates focused button/link
|
|
91
|
+
- Arrow keys navigate within component groups (radio buttons, tabs, menus)
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## ARIA Patterns (Common)
|
|
96
|
+
|
|
97
|
+
### Modal Dialog
|
|
98
|
+
```html
|
|
99
|
+
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
|
100
|
+
<h2 id="modal-title">Confirm Deletion</h2>
|
|
101
|
+
<!-- content -->
|
|
102
|
+
<button>Cancel</button>
|
|
103
|
+
<button>Delete</button>
|
|
104
|
+
</div>
|
|
105
|
+
```
|
|
106
|
+
On open: move focus to first focusable element or dialog title.
|
|
107
|
+
On close: return focus to the trigger element.
|
|
108
|
+
|
|
109
|
+
### Live Regions
|
|
110
|
+
```html
|
|
111
|
+
<!-- For dynamic content updates (toasts, status messages) -->
|
|
112
|
+
<div aria-live="polite" aria-atomic="true">
|
|
113
|
+
<!-- Status messages injected here -->
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<!-- For urgent updates (errors) -->
|
|
117
|
+
<div aria-live="assertive">
|
|
118
|
+
<!-- Error messages injected here -->
|
|
119
|
+
</div>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Loading States
|
|
123
|
+
```html
|
|
124
|
+
<button aria-disabled="true" aria-busy="true">
|
|
125
|
+
<span aria-hidden="true">⟳</span>
|
|
126
|
+
Saving...
|
|
127
|
+
</button>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Responsive and Dynamic Type
|
|
133
|
+
|
|
134
|
+
- Base font size: minimum **16px** on mobile (smaller = pinch-zoom for many users)
|
|
135
|
+
- Honor system text scaling: don't lock font sizes in px when users have increased system font size
|
|
136
|
+
- In React Native: use `Text` component which respects Dynamic Type automatically
|
|
137
|
+
- In web: use `rem` units for font sizes, not `px`
|
|
138
|
+
|
|
139
|
+
```css
|
|
140
|
+
/* GOOD — scales with user preference */
|
|
141
|
+
font-size: 1rem; /* = 16px at default, scales if user sets larger system font */
|
|
142
|
+
|
|
143
|
+
/* RISKY — overrides user preference */
|
|
144
|
+
font-size: 16px;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Motion Accessibility
|
|
150
|
+
|
|
151
|
+
All animations must respect `prefers-reduced-motion: reduce`. See `reference/motion.md`.
|
|
152
|
+
|
|
153
|
+
The `prefers-reduced-motion` check is an accessibility requirement (WCAG 2.3.3 AAA; WCAG 2.2 reduces to recommendation — but implement it regardless).
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Quick Accessibility Audit Checklist
|
|
158
|
+
|
|
159
|
+
Run through this before marking any design complete:
|
|
160
|
+
|
|
161
|
+
**Contrast:**
|
|
162
|
+
- [ ] All body text ≥ 4.5:1 against background
|
|
163
|
+
- [ ] Large text ≥ 3:1
|
|
164
|
+
- [ ] UI components (inputs, buttons) ≥ 3:1
|
|
165
|
+
- [ ] Placeholder text ≥ 4.5:1
|
|
166
|
+
- [ ] Focus rings ≥ 3:1 against adjacent colors
|
|
167
|
+
|
|
168
|
+
**Interaction:**
|
|
169
|
+
- [ ] All tap targets ≥ 44×44px
|
|
170
|
+
- [ ] 8px minimum gap between targets
|
|
171
|
+
- [ ] Focus ring visible on all interactive elements
|
|
172
|
+
- [ ] Tab order is logical
|
|
173
|
+
- [ ] Escape closes overlays
|
|
174
|
+
- [ ] No keyboard traps outside modals
|
|
175
|
+
|
|
176
|
+
**Semantics:**
|
|
177
|
+
- [ ] One h1 per page, heading hierarchy is sequential
|
|
178
|
+
- [ ] All images have meaningful alt text or alt=""
|
|
179
|
+
- [ ] Form labels associated with inputs
|
|
180
|
+
- [ ] Icon buttons have aria-label
|
|
181
|
+
- [ ] Error messages associated with fields (aria-describedby)
|
|
182
|
+
- [ ] Live regions for dynamic content
|
|
183
|
+
|
|
184
|
+
**Color:**
|
|
185
|
+
- [ ] No color-only meaning (+ icon, pattern, or text)
|
|
186
|
+
- [ ] Error states have visual indicator beyond color
|
|
187
|
+
|
|
188
|
+
**Motion:**
|
|
189
|
+
- [ ] prefers-reduced-motion handled
|
|
190
|
+
- [ ] Auto-playing video can be paused
|