@hegemonart/get-design-done 1.44.0 → 1.45.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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +41 -0
- package/README.md +2 -0
- package/agents/design-auditor.md +1 -0
- package/agents/design-executor.md +1 -1
- package/agents/motion-mapper.md +9 -5
- package/package.json +3 -1
- package/reference/color.md +34 -0
- package/reference/interaction.md +48 -0
- package/reference/motion.md +61 -302
- package/reference/registry.json +41 -4
- package/reference/registry.schema.json +49 -12
- package/reference/responsive.md +74 -0
- package/reference/spatial.md +38 -0
- package/reference/typography.md +48 -116
- package/reference/ux-writing.md +60 -0
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "Get Design Done — 5-stage agent-orchestrated design pipeline with 9 connections, handoff-first workflow, bidirectional Figma write-back, 22+ specialized agents, queryable knowledge layer (intel store, dependency analysis, learnings extraction), and a self-improvement loop (reflector, frontmatter + budget feedback, global-skills layer). v1.20.0 ships the SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream, and resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) for rate-limit + 429 + context-overflow recovery. Full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation (auto-tag + GitHub Release + release-time smoke test).",
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.45.0"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "get-design-done",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), Claude Design handoff, bidirectional Figma write-back, and a queryable intel store (.design/intel/) for dependency and learnings queries. Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation. Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
|
|
15
|
-
"version": "1.
|
|
15
|
+
"version": "1.45.0",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "hegemonart"
|
|
18
18
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "get-design-done",
|
|
3
3
|
"short_name": "gdd",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.45.0",
|
|
5
5
|
"description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), handoff-first workflow via Claude Design bundles, bidirectional Figma write-back (annotations, Code Connect), queryable intel store (`.design/intel/`) for O(1) design surface lookups, and self-improvement loop (reflector agent, frontmatter + budget feedback, global-skills layer at `~/.claude/gdd/global-skills/`). Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings, reflect, apply-reflections. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows, lint + schema + frontmatter + stale-ref + shellcheck + gitleaks + injection-scan + blocking size-budget) and release automation (auto-tag + GitHub Release + release-time smoke test). Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain. v1.27.7 ships gdd-mcp (Phase 27.7): 12 read-only MCP tools for sub-3s priming. v1.28.0 (Phase 28): Foundational References Tier 2 — 5 new reference files (color-theory, composition, proportion-systems, i18n, contrast-advanced), 2 verifier i18n probes + 1 explore i18n-readiness probe, 12 additive cross-link insertions across 10 existing references, 2 orthogonal audit-scoring lens-tags (composition_alignment + i18n_readiness).",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "hegemonart",
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,47 @@ All notable changes to get-design-done are documented here. Versions follow [sem
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [1.45.0] - 2026-06-02
|
|
8
|
+
|
|
9
|
+
### Phase 45 - Canonical Domain Reference Index
|
|
10
|
+
|
|
11
|
+
GDD has 38+ reference docs with flat indexing - agents loaded fragments by name and missed the rest, or
|
|
12
|
+
loaded all 5 motion files and wasted tokens. Phase 45 ships 7 navigation entry-points over the existing
|
|
13
|
+
content (it indexes, never re-authors). Planned and executed via the GSD pipeline (parallel research +
|
|
14
|
+
parallel authoring subagents). No new runtime dependency, no new egress.
|
|
15
|
+
|
|
16
|
+
### Breaking changes
|
|
17
|
+
|
|
18
|
+
- **Two CI gates now guard the domain indexes.** `npm run check:domain-links` fails if any cross-link in
|
|
19
|
+
the 7 entry-points points at a missing file or anchor; `npm run check:no-duplication` fails if an index
|
|
20
|
+
copies large blocks from the fragment it should only link. Contributors editing the 7
|
|
21
|
+
`reference/{typography,color,spatial,motion,interaction,responsive,ux-writing}.md` entries must keep
|
|
22
|
+
links resolving and keep entries link-only.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **7 domain-index entry-points** at `reference/{typography,color,spatial,motion,interaction,responsive,ux-writing}.md`,
|
|
27
|
+
each <=300 lines: a mission, a "use this when" index of the subordinate fragments, 3-5 rules-of-thumb, and
|
|
28
|
+
cross-domain see-also links. `motion.md` and `typography.md` were transformed in place; the other five are new.
|
|
29
|
+
- **Registry `domain-index` kind**: `reference/registry.schema.json` gains the type; the 7 entries register
|
|
30
|
+
as `domain-index` so skills can query indexes first and drill into detail second.
|
|
31
|
+
- **`scripts/check-domain-cross-links.cjs`** + **`scripts/check-no-duplication.cjs`** (maintainer-only) + the
|
|
32
|
+
two CI steps.
|
|
33
|
+
- **Consumer migration**: `motion-mapper` now loads `motion.md` (the index) and drills into a fragment only
|
|
34
|
+
when classifying against it (an 89% token cut versus loading all four motion fragments up front);
|
|
35
|
+
`design-auditor` and `design-executor` lead their reference reading with the domain indexes. Token-load
|
|
36
|
+
baseline at `test/fixtures/baselines/phase-45/token-load.json`.
|
|
37
|
+
|
|
38
|
+
### Notes
|
|
39
|
+
|
|
40
|
+
- 6-manifest lockstep at **v1.45.0** + `OFF_CADENCE_VERSIONS.add('1.45.0')` + 37 `manifests-version.txt`
|
|
41
|
+
baselines forward-propagated 1.44.0 -> 1.45.0. Tarball golden 869 -> 874 (+5 new shipped `reference/*.md`;
|
|
42
|
+
the two CI scripts are maintainer-only, not shipped).
|
|
43
|
+
- SC#9 (Phase 41 rule `references[]` migration to canonical entries) is deferred to a follow-up; the rule
|
|
44
|
+
links to `anti-patterns.md` still resolve, so the migration is a nice-to-have rather than a blocker.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
7
48
|
## [1.44.0] - 2026-06-02
|
|
8
49
|
|
|
9
50
|
### Phase 44 - Harness Capability Matrix
|
package/README.md
CHANGED
|
@@ -249,6 +249,8 @@ All 14 runtimes receive their native artifact layout (`skills/`, `command/`, `ag
|
|
|
249
249
|
|
|
250
250
|
**Harness capability matrix (v1.44.0).** The full per-harness support matrix (skill discovery, command syntax, MCP, install path, status) lives in **[`HARNESSES.md`](HARNESSES.md)** at the repo root, generated from `scripts/lib/manifest/harnesses.json` (the single source of truth; CI drift-gates it). Each harness carries an honest status (`tested` / `experimental` / `untested`) and a `last_verified` stamp; a freshness gate warns at 60 days and fails at 180 for `tested` harnesses, surfaced in `/gdd:health`. The 14-harness count above is the same SoT the matrix reads, so it cannot drift. The five deep-dive reference files (`reference/codex-tools.md`, `reference/gemini-tools.md`, `reference/peer-cli-capabilities.md`, `reference/peer-protocols.md`, `reference/runtime-models.md`) remain as appendices linked from the matrix. **No new runtime dependency.**
|
|
251
251
|
|
|
252
|
+
**Domain reference index (v1.45.0).** The 38+ reference docs are now navigated through 7 canonical entry-points - `reference/{typography,color,spatial,motion,interaction,responsive,ux-writing}.md` - each indexing its subordinate fragments with a "use this when" pointer plus a handful of rules-of-thumb. Design skills load the relevant domain index first and drill into a fragment only when needed (motion-mapper dropped roughly 89% of its up-front reference tokens this way). The indexes link, never copy: `check:domain-links` fails CI on a broken cross-link and `check:no-duplication` fails on large copy-paste. The detailed fragments stay in place as the drill-in targets. **No new runtime dependency.**
|
|
253
|
+
|
|
252
254
|
Verify with:
|
|
253
255
|
|
|
254
256
|
```
|
package/agents/design-auditor.md
CHANGED
|
@@ -45,6 +45,7 @@ Minimum expected files:
|
|
|
45
45
|
- `.design/DESIGN-CONTEXT.md` - goals, brand direction, design decisions (D-XX)
|
|
46
46
|
- `.design/DESIGN-PLAN.md` - planned tasks and acceptance criteria
|
|
47
47
|
- `.design/tasks/` - what was actually done (glob all task files)
|
|
48
|
+
- **Domain-index navigation (Phase 45):** the 7 entry-points `reference/{typography,color,spatial,motion,interaction,responsive,ux-writing}.md` index every fragment below. For a pillar, load the relevant domain index first, then drill into the specific fragments it lists only as the pillar needs them - this is the cheap navigation layer over the detailed fragments.
|
|
48
49
|
- `reference/audit-scoring.md` - existing 7-category scoring rubric (understand, do not duplicate)
|
|
49
50
|
- `reference/brand-voice.md` - voice axes, archetype library, and tone-by-context table (use when auditing Pillar 1: Copy)
|
|
50
51
|
- `reference/gestalt.md` - 8 Gestalt principles with scoring rubrics (use when auditing Pillar 2: Visual Hierarchy)
|
|
@@ -34,7 +34,7 @@ The orchestrating stage supplies a `<required_reading>` block in the prompt. Rea
|
|
|
34
34
|
- `.design/STATE.md` - pipeline state (decisions, blockers, must-haves)
|
|
35
35
|
- `.design/DESIGN-PLAN.md` - full task list (your task is identified by task_id)
|
|
36
36
|
- `.design/DESIGN-CONTEXT.md` - brand decisions, constraints, locked choices
|
|
37
|
-
- The reference file(s) relevant to the task type (e.g., `reference/typography.md` for a typography task)
|
|
37
|
+
- The reference file(s) relevant to the task type (e.g., `reference/typography.md` for a typography task). The 7 domain-index entry-points `reference/{typography,color,spatial,motion,interaction,responsive,ux-writing}.md` (Phase 45) are the navigation start: load the index, drill into the fragments it lists only as the task needs them.
|
|
38
38
|
|
|
39
39
|
**Invariant:** read all listed files FIRST, before making any changes.
|
|
40
40
|
|
package/agents/motion-mapper.md
CHANGED
|
@@ -24,11 +24,15 @@ You inventory motion and animation patterns. Zero session memory. You do not mod
|
|
|
24
24
|
## Required Reading
|
|
25
25
|
|
|
26
26
|
- `.design/STATE.md`
|
|
27
|
-
- `reference/motion.md` (if present)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
-
|
|
27
|
+
- `reference/motion.md` (if present) - **the motion domain-index (Phase 45): start here.** It indexes the
|
|
28
|
+
motion fragments below with a "use this when" pointer for each. Load a specific fragment ONLY when you
|
|
29
|
+
reach the classification step that needs it (drill-in), not all of them up front - this is the bulk of
|
|
30
|
+
the token saving (the index is ~1.7k tokens vs ~15k for all four fragments).
|
|
31
|
+
- Drill-in fragments (load on demand, per the index in `motion.md`):
|
|
32
|
+
- `reference/motion-advanced.md` - advanced patterns: spring physics, scroll-driven, FLIP, View Transitions API, gesture/drag mechanics, clip-path patterns, blur crossfades, Framer Motion hardware-accel gotcha
|
|
33
|
+
- `reference/motion-easings.md` - 12 canonical easing presets; classify each detected easing against this catalog
|
|
34
|
+
- `reference/motion-transition-taxonomy.md` - 8 transition families; classify page/route transitions against this taxonomy
|
|
35
|
+
- `reference/motion-spring.md` - spring presets; classify spring configs against gentle/wobbly/stiff/slow
|
|
32
36
|
- Any files supplied by the orchestrator
|
|
33
37
|
|
|
34
38
|
## Scan Strategy
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hegemonart/get-design-done",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.0",
|
|
4
4
|
"description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
|
|
5
5
|
"author": "Hegemon",
|
|
6
6
|
"homepage": "https://github.com/hegemonart/get-design-done",
|
|
@@ -69,6 +69,8 @@
|
|
|
69
69
|
"build:harnesses:check": "node scripts/generate-harnesses-md.cjs --check",
|
|
70
70
|
"check:harness-freshness": "node scripts/check-harness-freshness.cjs",
|
|
71
71
|
"verify:harness": "node scripts/verify-harness.cjs",
|
|
72
|
+
"check:domain-links": "node scripts/check-domain-cross-links.cjs",
|
|
73
|
+
"check:no-duplication": "node scripts/check-no-duplication.cjs",
|
|
72
74
|
"sync:rule-catalogue": "node scripts/sync-rule-catalogue.cjs --check",
|
|
73
75
|
"validate:manifest": "node scripts/validate-manifest.cjs --check",
|
|
74
76
|
"validate:schemas": "node --experimental-strip-types scripts/validate-schemas.ts",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Color - Palette, Contrast, and Aesthetic Direction
|
|
2
|
+
|
|
3
|
+
Color governs how palettes are constructed, how semantic color roles are assigned, how
|
|
4
|
+
contrast compliance is verified, and how the aesthetic style direction is confirmed.
|
|
5
|
+
Read `color-theory.md` when building a new palette from scratch. Read `palette-catalog.md`
|
|
6
|
+
when adopting an industry-vertical baseline. Read `contrast-advanced.md` for APCA
|
|
7
|
+
thresholds on thin or colored text. Read `style-vocabulary.md` to confirm whether an
|
|
8
|
+
aesthetic style's color requirements fit the product type. Does not cover type sizing for
|
|
9
|
+
legibility (see `typography.md`) or dark-mode implementation steps beyond OKLCH token
|
|
10
|
+
generation (see `color-theory.md`).
|
|
11
|
+
|
|
12
|
+
## Fragment Index
|
|
13
|
+
|
|
14
|
+
| Fragment | When to load |
|
|
15
|
+
|---|---|
|
|
16
|
+
| [`./color-theory.md`](./color-theory.md) | constructing a palette, choosing a color space, building OKLCH harmonies, animating color, auditing under color-blindness simulation |
|
|
17
|
+
| [`./palette-catalog.md`](./palette-catalog.md) | adopting a pre-built industry-vertical palette as a baseline token set (40+ verticals, WCAG-verified) |
|
|
18
|
+
| [`./contrast-advanced.md`](./contrast-advanced.md) | computing text/UI contrast beyond WCAG 2.1 AA - especially for thin, large, or colored text where WCAG 2.1 misranks |
|
|
19
|
+
| [`./style-vocabulary.md`](./style-vocabulary.md) | confirming a UI aesthetic direction: does the style require dark mode, what are its signature color effects, which product types should avoid it |
|
|
20
|
+
|
|
21
|
+
## Rules of Thumb
|
|
22
|
+
|
|
23
|
+
1. Author new palette tokens in OKLCH, not HSL or hex. OKLCH ΔL/ΔC/Δh steps are perceptually uniform - equal numeric jumps produce equal perceived brightness jumps. HSL's lightness channel is not perceptual.
|
|
24
|
+
2. Never rely on color alone to convey state (error, warning, success). Always pair with an icon, label, or pattern - WCAG 1.4.1.
|
|
25
|
+
3. For the APCA dual-target pattern: meet WCAG 2.1 AA (4.5:1 for body text) AND check Lc 60 (APCA) for thin weights and colored backgrounds. The two systems can disagree on the same pair.
|
|
26
|
+
4. Check every palette under deutan (most common), protan, and tritan simulations before shipping. The color-blindness palettes in `color-theory.md` provide pre-vetted swap sets.
|
|
27
|
+
|
|
28
|
+
## See Also
|
|
29
|
+
|
|
30
|
+
- Typography legibility at small sizes: [`./typography.md`](./typography.md)
|
|
31
|
+
- OKLCH interpolation in color animations: [`./motion.md`](./motion.md)
|
|
32
|
+
- Spatial depth via shadow and elevation: [`./spatial.md`](./spatial.md)
|
|
33
|
+
- Healthcare: critical-value flags not color-only: [`./domains/healthcare-patterns.md`](./domains/healthcare-patterns.md)
|
|
34
|
+
- Finance: gain/loss color rules: [`./domains/finance-patterns.md`](./domains/finance-patterns.md)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Interaction - Domain Index
|
|
2
|
+
|
|
3
|
+
This domain covers how users trigger, navigate, and recover from actions: accessibility requirements, component API quality, form patterns, information architecture, onboarding, and the emotional layer.
|
|
4
|
+
|
|
5
|
+
<!-- Phase 45 domain-index: loads this file instead of individual interaction fragments -->
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Mission
|
|
10
|
+
|
|
11
|
+
Interaction is the broadest design domain. It governs every point where a user acts on the interface and the interface responds. Load only the specific fragment for the task at hand using the index below. Does not cover visual placement of interactive elements (see `spatial.md`) or copy for UI elements (see `ux-writing.md`).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Fragment Index
|
|
16
|
+
|
|
17
|
+
| Fragment | When to load |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `./accessibility.md` | WCAG 2.1 AA thresholds, keyboard navigation, focus management, ARIA roles. Required for every interactive surface without exception. |
|
|
20
|
+
| `./component-authoring.md` | Designing or reviewing component APIs: P-01 Minimal API through P-06 Edge Honesty, composability, defaults, animation-as-state |
|
|
21
|
+
| `./form-patterns.md` | Forms are in scope: label position, validation timing, autofill tokens, password UX, CAPTCHA ethics |
|
|
22
|
+
| `./information-architecture.md` | Navigation structure is in scope: hub-and-spoke, faceted nav, card sort benchmarks, wayfinding |
|
|
23
|
+
| `./onboarding-progressive-disclosure.md` | First-run experience is in scope: empty-state patterns, product tours, checklist onboarding, Aha-moment mapping |
|
|
24
|
+
| `./emotional-design.md` | Holistic quality overlay after pillar scoring: Norman visceral/behavioral/reflective three-level lens |
|
|
25
|
+
| `./components/README.md` | Auditing a specific component against benchmark: entry to 38 spec files (accordion through tree) |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Rules of Thumb
|
|
30
|
+
|
|
31
|
+
1. Accessibility is not a final checklist - build it in from the start. Every interactive component begins with the WAI-ARIA contract from `accessibility.md`, not a retrofit after design is complete.
|
|
32
|
+
2. P-01 Minimal API from `component-authoring.md`: a component's API surface is its test surface. Every prop that can be removed should be removed.
|
|
33
|
+
3. Form label position: top-aligned is the default for all but settings-page scan forms. Placeholder-as-label is a WCAG 1.3.5 failure on any form with more than 3 fields.
|
|
34
|
+
4. Empty-state onboarding outperforms product tours by completion rate for creation tools. Only use a tour when unfamiliar terminology requires context, and cap it at 5 steps.
|
|
35
|
+
5. The emotional design lens applies after technical and usability requirements are met. Visceral quality (appearance) and behavioral quality (task flow) both need to be solid before reflective quality (brand meaning) is addressed.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Cross-Domain See Also
|
|
40
|
+
|
|
41
|
+
- Gesture animation and animation-as-state: `reference/motion.md`
|
|
42
|
+
- Spatial grouping informs IA mental models: `reference/spatial.md`
|
|
43
|
+
- Touch target sizing differs by platform: `reference/responsive.md`
|
|
44
|
+
- Error message copy and empty-state copy: `reference/ux-writing.md`
|
|
45
|
+
- Healthcare form patterns (PHI isolation): `reference/domains/healthcare-patterns.md`
|
|
46
|
+
- Civic one-thing-per-page forms: `reference/domains/civic-patterns.md`
|
|
47
|
+
- Typography: `reference/typography.md`
|
|
48
|
+
- Color: `reference/color.md`
|
package/reference/motion.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
-
# Motion
|
|
1
|
+
# Motion - Animation Domain Index
|
|
2
2
|
|
|
3
|
-
Based on Emil Kowalski's design engineering philosophy. Apply these rules in order
|
|
3
|
+
Based on Emil Kowalski's design engineering philosophy. Apply these rules in order. Do not skip to "how should this animate" before answering "should this animate."
|
|
4
|
+
|
|
5
|
+
<!-- Phase 45 domain-index: loads this file instead of individual motion fragments -->
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Mission
|
|
10
|
+
|
|
11
|
+
Motion governs animation decisions across the UI: whether to animate, duration budgets, easing choices, spring physics, transition taxonomy, and interpolation. Read this file first for the decision framework and core rules, then drill into the specialist fragment below. Does not cover CSS layout transitions (see `spatial.md`) or OS-level reduced-motion policy (see `responsive.md`).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Fragment Index
|
|
16
|
+
|
|
17
|
+
| Fragment | When to load |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `./motion-easings.md` | Choosing or auditing easing curve values: 12 canonical `--ease-*` presets, cubic-bezier equivalents, 60fps settle-times |
|
|
20
|
+
| `./motion-spring.md` | Interaction is draggable or needs physics feel: gentle/wobbly/stiff/slow presets, Framer Motion and React Spring syntax |
|
|
21
|
+
| `./motion-transition-taxonomy.md` | Classifying page or route transitions: 8 families (3d, blur, cover, destruction, dissolve, distortion, grid, light) |
|
|
22
|
+
| `./motion-interpolate.md` | Mapping input-to-output ranges: progress/scroll/gesture/time-linked animations, 4 extrapolation modes |
|
|
23
|
+
| `./motion-advanced.md` | Advanced platform APIs: FLIP, scroll-driven, View Transitions, gesture/drag, clip-path, WAAPI |
|
|
24
|
+
| `./framer-motion-patterns.md` | Codebase uses Framer Motion: spring/tween config, AnimatePresence, variants, gestures, a11y, bounce:0 rule |
|
|
4
25
|
|
|
5
26
|
---
|
|
6
27
|
|
|
@@ -12,7 +33,7 @@ Based on Emil Kowalski's design engineering philosophy. Apply these rules in ord
|
|
|
12
33
|
|---|---|
|
|
13
34
|
| 100+/day - keyboard shortcuts, command palette, list navigation | **No animation. Ever.** |
|
|
14
35
|
| Tens/day - hover states, toggles, tab switching | Remove or keep to <80ms. No delay. |
|
|
15
|
-
| Occasional - modals opening, drawers, toasts | Standard animation (150
|
|
36
|
+
| Occasional - modals opening, drawers, toasts | Standard animation (150-300ms) |
|
|
16
37
|
| Rare - onboarding, celebrations, first-time flows | Can add personality and delight |
|
|
17
38
|
| Once - loading splash, page transitions | Full animation budget |
|
|
18
39
|
|
|
@@ -25,9 +46,9 @@ Valid animation purposes only. If it doesn't serve one of these, remove it.
|
|
|
25
46
|
| Purpose | Example |
|
|
26
47
|
|---|---|
|
|
27
48
|
| **Spatial consistency** | Toast enters/exits same edge each time |
|
|
28
|
-
| **State indication** | Button morphs to show loading
|
|
49
|
+
| **State indication** | Button morphs to show loading to success |
|
|
29
50
|
| **Cause-effect explanation** | Item deletion - item flies to trash |
|
|
30
|
-
| **Feedback** | Button scales
|
|
51
|
+
| **Feedback** | Button scales on press |
|
|
31
52
|
| **Prevent jarring changes** | Content appearing/disappearing needs transition |
|
|
32
53
|
|
|
33
54
|
Invalid purposes: "It looks cool", "It feels modern", "Other apps do it."
|
|
@@ -42,44 +63,28 @@ Invalid purposes: "It looks cool", "It feels modern", "Other apps do it."
|
|
|
42
63
|
| **Interactive/draggable** | Spring physics | Follows finger/cursor naturally |
|
|
43
64
|
| **Bounce/elastic** | **Never** | Feels toy-like and dated |
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
```css
|
|
47
|
-
/* Enter */
|
|
48
|
-
transition: transform 200ms cubic-bezier(0, 0, 0.2, 1); /* ease-out */
|
|
49
|
-
|
|
50
|
-
/* Exit */
|
|
51
|
-
transition: transform 150ms cubic-bezier(0.4, 0, 1, 1); /* ease-in */
|
|
52
|
-
|
|
53
|
-
/* Transition */
|
|
54
|
-
transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1); /* ease-in-out */
|
|
55
|
-
```
|
|
66
|
+
See `reference/motion-easings.md` for the full `--ease-*` token catalog.
|
|
56
67
|
|
|
57
68
|
### Question 4: What Duration?
|
|
58
69
|
|
|
59
70
|
| Animation type | Duration | Notes |
|
|
60
71
|
|---|---|---|
|
|
61
|
-
| Micro-interactions | 80
|
|
62
|
-
| Component enter/exit | 150
|
|
63
|
-
| Page transitions | 200
|
|
64
|
-
| Complex/orchestrated |
|
|
72
|
+
| Micro-interactions | 80-150ms | Hover, press, toggle |
|
|
73
|
+
| Component enter/exit | 150-250ms | Modals, drawers, dropdowns |
|
|
74
|
+
| Page transitions | 200-350ms | Route changes |
|
|
75
|
+
| Complex/orchestrated | <=400ms | Multi-step, staggered reveals |
|
|
65
76
|
| **Never exceed** | 400ms | Anything longer feels broken |
|
|
66
77
|
|
|
67
|
-
**Exit faster than enter**: Exit animations should run at **60
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
Enter: 250ms
|
|
71
|
-
Exit: 150ms (60% of 250)
|
|
72
|
-
```
|
|
78
|
+
**Exit faster than enter**: Exit animations should run at **60-70%** of the enter duration.
|
|
73
79
|
|
|
74
80
|
### Question 5: Only Animate `transform` and `opacity`
|
|
75
81
|
|
|
76
|
-
**Only these properties animate on the GPU:**
|
|
77
82
|
```css
|
|
78
|
-
/* SAFE */
|
|
83
|
+
/* SAFE - GPU-accelerated */
|
|
79
84
|
transform: translateX(), translateY(), scale(), rotate()
|
|
80
|
-
opacity: 0
|
|
85
|
+
opacity: 0 to 1
|
|
81
86
|
|
|
82
|
-
/* DANGEROUS
|
|
87
|
+
/* DANGEROUS - triggers layout/paint */
|
|
83
88
|
width, height, top, left, margin, padding, font-size
|
|
84
89
|
```
|
|
85
90
|
|
|
@@ -89,319 +94,73 @@ Exception: `filter` (blur) is GPU-accelerated in modern browsers but battery-exp
|
|
|
89
94
|
|
|
90
95
|
## Stagger Rules
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
- Direction: top-to-bottom OR left-to-right - never random
|
|
96
|
-
|
|
97
|
-
```css
|
|
98
|
-
.item:nth-child(1) { animation-delay: 0ms; }
|
|
99
|
-
.item:nth-child(2) { animation-delay: 40ms; }
|
|
100
|
-
.item:nth-child(3) { animation-delay: 80ms; }
|
|
101
|
-
/* etc. — cap at ~6 staggered items */
|
|
102
|
-
```
|
|
97
|
+
- Stagger delay: **30-50ms** per item
|
|
98
|
+
- Maximum stagger depth: **6-8 items** (items beyond that appear simultaneously)
|
|
99
|
+
- Direction: top-to-bottom OR left-to-right, never random
|
|
103
100
|
|
|
104
101
|
---
|
|
105
102
|
|
|
106
103
|
## Press Feedback
|
|
107
104
|
|
|
108
|
-
Every clickable element must give visual feedback within **100ms** of interaction.
|
|
105
|
+
Every clickable element must give visual feedback within **100ms** of interaction. The canonical scale value for press feedback is **`0.96`**.
|
|
106
|
+
|
|
107
|
+
- Never use `scale(0.95)` - too large, feels unresponsive
|
|
108
|
+
- Never use `scale(0.97)` or higher - imperceptible at high DPI
|
|
109
|
+
- `0.96` is the correct value for standard interactive elements
|
|
109
110
|
|
|
110
111
|
```css
|
|
111
112
|
button:active {
|
|
112
|
-
transform: scale(0.
|
|
113
|
+
transform: scale(0.96);
|
|
113
114
|
transition: transform 80ms ease-out;
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
/* On release */
|
|
117
|
-
button:not(:active) {
|
|
118
|
-
transform: scale(1);
|
|
119
|
-
transition: transform 150ms ease-out;
|
|
120
|
-
}
|
|
121
116
|
```
|
|
122
117
|
|
|
123
|
-
Scale range: **0.95–0.98** for buttons. **0.97** is the safest default.
|
|
124
|
-
Never scale below 0.90 - it looks broken.
|
|
125
|
-
|
|
126
118
|
---
|
|
127
119
|
|
|
128
120
|
## `prefers-reduced-motion`
|
|
129
121
|
|
|
130
|
-
Always respect this. It
|
|
122
|
+
Always respect this. It is not optional.
|
|
131
123
|
|
|
132
124
|
```css
|
|
133
125
|
@media (prefers-reduced-motion: reduce) {
|
|
134
|
-
*,
|
|
135
|
-
*::before,
|
|
136
|
-
*::after {
|
|
126
|
+
*, *::before, *::after {
|
|
137
127
|
animation-duration: 0.01ms !important;
|
|
138
|
-
animation-iteration-count: 1 !important;
|
|
139
128
|
transition-duration: 0.01ms !important;
|
|
140
129
|
scroll-behavior: auto !important;
|
|
141
130
|
}
|
|
142
131
|
}
|
|
143
132
|
```
|
|
144
133
|
|
|
145
|
-
Or in JavaScript:
|
|
146
|
-
```js
|
|
147
|
-
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
148
|
-
if (!prefersReduced) {
|
|
149
|
-
// Run animation
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## What Never To Animate
|
|
156
|
-
|
|
157
|
-
- Keyboard shortcuts and commands (too frequent)
|
|
158
|
-
- Tab switching within a page
|
|
159
|
-
- Filter/sort toggles on data tables
|
|
160
|
-
- Expanding/collapsing sidebar navigation items during heavy use
|
|
161
|
-
- Any interaction the user will perform 50+ times in a session
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## The Invisible Detail Rule
|
|
166
|
-
|
|
167
|
-
The best animations are ones users cannot describe but notice when absent. Signs of this:
|
|
168
|
-
- The interaction feels "snappy" or "responsive" without thinking about why
|
|
169
|
-
- Removing the animation makes the UI feel broken
|
|
170
|
-
- Users say "it feels premium" but can't point to any specific feature
|
|
171
|
-
|
|
172
|
-
This is the goal. Not "look at this animation" - "why does this feel so good to use?"
|
|
173
|
-
|
|
174
134
|
---
|
|
175
135
|
|
|
176
|
-
## Quick
|
|
136
|
+
## Quick Audit Checklist
|
|
177
137
|
|
|
178
138
|
- [ ] No animation on keyboard-triggered actions
|
|
179
|
-
- [ ] All durations
|
|
139
|
+
- [ ] All durations <=400ms
|
|
180
140
|
- [ ] Exit < enter duration
|
|
181
141
|
- [ ] Only `transform` and `opacity` for performance
|
|
182
142
|
- [ ] `prefers-reduced-motion` implemented
|
|
183
|
-
- [ ] Stagger
|
|
143
|
+
- [ ] Stagger <=50ms per item, capped at 6-8 items
|
|
184
144
|
- [ ] Press feedback on all interactive elements
|
|
185
145
|
- [ ] No bounce/elastic easing anywhere
|
|
186
146
|
- [ ] All animations have a defined purpose
|
|
187
147
|
|
|
188
148
|
---
|
|
189
149
|
|
|
190
|
-
##
|
|
191
|
-
|
|
192
|
-
Spring-based animation replaces duration-based tweening with physics parameters
|
|
193
|
-
(stiffness, damping, mass). Output feels more organic and adapts to interruption.
|
|
194
|
-
|
|
195
|
-
### React Spring
|
|
196
|
-
|
|
197
|
-
```jsx
|
|
198
|
-
import { useSpring, animated } from '@react-spring/web';
|
|
199
|
-
|
|
200
|
-
const styles = useSpring({
|
|
201
|
-
from: { opacity: 0, transform: 'translateY(20px)' },
|
|
202
|
-
to: { opacity: 1, transform: 'translateY(0px)' },
|
|
203
|
-
config: { tension: 170, friction: 26 } // default preset
|
|
204
|
-
});
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
React Spring presets:
|
|
208
|
-
|
|
209
|
-
| Preset | tension | friction | Character |
|
|
210
|
-
|--------|---------|----------|-----------|
|
|
211
|
-
| default | 170 | 26 | balanced |
|
|
212
|
-
| gentle | 120 | 14 | smooth, leisurely |
|
|
213
|
-
| wobbly | 180 | 12 | playful bounce |
|
|
214
|
-
| stiff | 210 | 20 | snappy |
|
|
215
|
-
| slow | 280 | 60 | slow and deliberate |
|
|
216
|
-
| molasses | 280 | 120 | very slow, no bounce |
|
|
217
|
-
|
|
218
|
-
### Framer Motion
|
|
219
|
-
|
|
220
|
-
```jsx
|
|
221
|
-
<motion.div
|
|
222
|
-
animate={{ x: 100 }}
|
|
223
|
-
transition={{ type: "spring", stiffness: 100, damping: 15, mass: 1 }}
|
|
224
|
-
/>
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Parameter guidance:
|
|
228
|
-
|
|
229
|
-
| Param | Range | Effect |
|
|
230
|
-
|-------|-------|--------|
|
|
231
|
-
| stiffness | 50–300 | higher = snappier arrival |
|
|
232
|
-
| damping | 10–40 | higher = less oscillation |
|
|
233
|
-
| mass | 0.5–2 | higher = more inertia, slower response |
|
|
234
|
-
|
|
235
|
-
Rule of thumb: for UI micro-interactions use stiffness 150–250, damping 20–30, mass 1.
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Scroll-Triggered Animations
|
|
240
|
-
|
|
241
|
-
Use IntersectionObserver for scroll-reveal effects - it replaces scroll-event
|
|
242
|
-
listeners with a throttled browser-native API.
|
|
243
|
-
|
|
244
|
-
### Basic pattern
|
|
245
|
-
|
|
246
|
-
```js
|
|
247
|
-
const observer = new IntersectionObserver((entries) => {
|
|
248
|
-
entries.forEach(entry => {
|
|
249
|
-
if (entry.isIntersecting) {
|
|
250
|
-
entry.target.classList.add('in-view');
|
|
251
|
-
// Optional: disconnect after first trigger
|
|
252
|
-
// observer.unobserve(entry.target);
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
}, {
|
|
256
|
-
threshold: 0.1,
|
|
257
|
-
rootMargin: '0px 0px -100px 0px' // trigger 100px before entering viewport bottom
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Threshold guidance
|
|
264
|
-
|
|
265
|
-
| threshold | Meaning |
|
|
266
|
-
|-----------|---------|
|
|
267
|
-
| 0.0 | element enters viewport edge |
|
|
268
|
-
| 0.1–0.25 | element partially visible (most common for reveals) |
|
|
269
|
-
| 0.5 | element half-visible |
|
|
270
|
-
| 1.0 | element fully visible |
|
|
271
|
-
|
|
272
|
-
### Once vs repeat
|
|
273
|
-
|
|
274
|
-
- **Once** - call `observer.unobserve(entry.target)` after first intersection.
|
|
275
|
-
Use for: hero reveals, one-shot entrance animations, stat counters.
|
|
276
|
-
- **Repeat** - leave observer active. Use for: progress indicators, parallax effects,
|
|
277
|
-
sticky nav state changes.
|
|
278
|
-
|
|
279
|
-
### Performance rules
|
|
280
|
-
|
|
281
|
-
1. Animate only `transform` and `opacity` (GPU-accelerated). Avoid `top`, `left`, `width`, `height`.
|
|
282
|
-
2. No debounce/throttle needed - IntersectionObserver is already throttled by the browser.
|
|
283
|
-
3. For many elements, share a single observer instance and call `observe()` once per element.
|
|
284
|
-
4. Prefer CSS transitions triggered by a class toggle over requestAnimationFrame loops.
|
|
285
|
-
5. Use `will-change: transform, opacity` sparingly (only on elements that animate repeatedly).
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## MIFB Micro-Motion Extensions
|
|
290
|
-
Source: jakubkrehel/make-interfaces-feel-better (MIT) - motion.md
|
|
291
|
-
|
|
292
|
-
### Interruptible Animations
|
|
293
|
-
|
|
294
|
-
Use CSS transitions for interactive elements because transitions retarget mid-animation - when a user moves their cursor away before a hover animation completes, the transition reverses smoothly from wherever it currently is. Keyframe animations restart from the beginning, creating a jarring jump.
|
|
295
|
-
|
|
296
|
-
**Decision rule:**
|
|
297
|
-
- Interactive states (hover, focus, active, pressed): always CSS transitions
|
|
298
|
-
- Orchestrated sequences, entrance effects, data-driven animations: keyframe or JS animation
|
|
299
|
-
|
|
300
|
-
```css
|
|
301
|
-
/* Good — transition retargets smoothly */
|
|
302
|
-
.button { transition: background-color 150ms ease-out; }
|
|
303
|
-
|
|
304
|
-
/* Avoid for interactive — restarts on interruption */
|
|
305
|
-
.button:hover { animation: hover-bg 150ms ease-out forwards; }
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
### Split-and-Stagger Enter/Exit
|
|
309
|
-
|
|
310
|
-
For multi-element entrances (card grids, lists, feature sections):
|
|
311
|
-
|
|
312
|
-
- Default stagger: 100ms between elements
|
|
313
|
-
- Heading words: 80ms per word
|
|
314
|
-
- Entrance transform: `opacity: 0 → 1` + `translateY(12px → 0)` + `blur(4px → 0)`
|
|
315
|
-
- Entrance duration: 300ms, `ease-out`
|
|
316
|
-
- Exit transform: `opacity: 1 → 0` + `translateY(0 → -12px)` (opposite direction, smaller offset)
|
|
317
|
-
- Exit duration: 150ms (half the entrance duration - exits should be faster)
|
|
318
|
-
|
|
319
|
-
The blur component adds a depth cue that makes entrances feel less flat. Keep blur modest (4px) - the goal is a subtle focus effect, not a visible blur.
|
|
320
|
-
|
|
321
|
-
### Contextual Icon Animations - Cross-Fade Pattern
|
|
322
|
-
|
|
323
|
-
When swapping two icons (e.g., play ↔ pause, chevron-up ↔ chevron-down, bookmark ↔ bookmarked), use this exact cross-fade spec:
|
|
324
|
-
|
|
325
|
-
**Framer Motion spring (preferred):**
|
|
326
|
-
- `scale: 0.25 → 1` (entering), `scale: 1 → 0.25` (exiting)
|
|
327
|
-
- `opacity: 0 → 1` (entering), `opacity: 1 → 0` (exiting)
|
|
328
|
-
- `filter: blur(4px) → blur(0)` (entering), `blur(0) → blur(4px)` (exiting)
|
|
329
|
-
- `transition: { type: "spring", duration: 0.3, bounce: 0 }` - **bounce MUST be 0**
|
|
150
|
+
## Rules of Thumb
|
|
330
151
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
-
|
|
335
|
-
|
|
336
|
-
The scale + blur combination creates a focus-snap effect that feels intentional rather than mechanical. The `bounce: 0` hard constraint exists because any bounce on a 0.25-scale origin point makes icons appear to "pop" invasively.
|
|
337
|
-
|
|
338
|
-
### Scale on Press - Canonical Value
|
|
339
|
-
|
|
340
|
-
The canonical scale value for press feedback is **`0.96`**.
|
|
341
|
-
|
|
342
|
-
Rules:
|
|
343
|
-
- Never use `scale(0.95)` - too large, feels unresponsive
|
|
344
|
-
- Never use `scale(0.97)` - too subtle at high DPI, not perceived as feedback
|
|
345
|
-
- Never use `scale(0.98)` or higher - imperceptible
|
|
346
|
-
- `0.96` is the ONLY correct value for standard interactive elements
|
|
347
|
-
|
|
348
|
-
Tailwind: `active:scale-[0.96]`
|
|
349
|
-
Framer: `whileTap={{ scale: 0.96 }}`
|
|
350
|
-
|
|
351
|
-
For primary CTAs where maximum tactility is needed (purchase, send, confirm):
|
|
352
|
-
use `0.96` with a shadow reduction: `box-shadow: none` during press.
|
|
353
|
-
|
|
354
|
-
Deprecation note: earlier versions of `reference/checklists.md` referenced `scale(0.97)`. That entry has been reconciled. **0.96 is the canonical value.**
|
|
355
|
-
|
|
356
|
-
### AnimatePresence initial={false}
|
|
357
|
-
|
|
358
|
-
When `AnimatePresence` wraps UI that exists in the DOM before it enters the animation scope (e.g., a tab panel that renders its first tab immediately, a dropdown that's already open on first load), use `initial={false}`:
|
|
359
|
-
|
|
360
|
-
```tsx
|
|
361
|
-
<AnimatePresence initial={false}>
|
|
362
|
-
{isOpen && <motion.div key="panel" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} />}
|
|
363
|
-
</AnimatePresence>
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
Without `initial={false}`, Framer will animate the FIRST render of children - meaning UI that's immediately visible on page load will "fade in" unnecessarily. This creates a flash/flicker that signals poor craftsmanship.
|
|
367
|
-
|
|
368
|
-
**Rule:** Any `AnimatePresence` wrapping persistent UI should have `initial={false}`.
|
|
369
|
-
|
|
370
|
-
### will-change - GPU Property Table
|
|
371
|
-
|
|
372
|
-
Only add `will-change` when you observe first-frame stutter on lower-end hardware. Do NOT add it preemptively - it consumes GPU memory continuously for every element that has it.
|
|
373
|
-
|
|
374
|
-
GPU-compositable properties (safe with will-change):
|
|
375
|
-
| Property | will-change value |
|
|
376
|
-
|----------|------------------|
|
|
377
|
-
| transform (translate, scale, rotate) | `transform` |
|
|
378
|
-
| opacity | `opacity` |
|
|
379
|
-
| filter (blur, brightness, contrast) | `filter` |
|
|
380
|
-
| clip-path | `clip-path` |
|
|
381
|
-
|
|
382
|
-
Never use `will-change: all` or `will-change: contents` - this forces the entire element and its subtree onto a new compositor layer, thrashing memory.
|
|
383
|
-
|
|
384
|
-
Remove `will-change` after the animation completes if applied dynamically:
|
|
385
|
-
```js
|
|
386
|
-
element.addEventListener('transitionend', () => element.style.willChange = 'auto')
|
|
387
|
-
```
|
|
152
|
+
1. Keyboard-initiated actions (command palette, list navigation, shortcuts) must have zero animation. They repeat hundreds of times daily and every ms is felt.
|
|
153
|
+
2. Default to named spring presets (gentle/wobbly/stiff/slow) rather than raw stiffness/damping numbers; presets are tuned for 60fps settle-time and predictable feel.
|
|
154
|
+
3. Always use `--ease-*` CSS custom property tokens rather than inline `cubic-bezier()` strings; tokens keep easing consistent and respect `prefers-reduced-motion`.
|
|
155
|
+
4. OKLCH is the correct color space for animated color transitions; sRGB interpolation produces muddy mid-transition colors. See `reference/color-theory.md` for color interpolation in animation.
|
|
388
156
|
|
|
389
157
|
---
|
|
390
158
|
|
|
391
|
-
##
|
|
392
|
-
|
|
393
|
-
For spring physics, scroll-driven animation, FLIP, View Transitions API, gesture & drag mechanics, clip-path animation patterns, blur-to-mask crossfades, WAAPI, Framer Motion hardware-acceleration gotcha, motion cohesion & personality, and the next-day slow-motion review process, see:
|
|
394
|
-
|
|
395
|
-
→ **`reference/motion-advanced.md`** (Phase 18)
|
|
396
|
-
|
|
397
|
-
For the canonical easing catalog (`--ease-*` tokens, cubic-bezier equivalents, 60fps settle-times):
|
|
398
|
-
|
|
399
|
-
→ **`reference/motion-easings.md`** (Phase 18)
|
|
400
|
-
|
|
401
|
-
For spring parameter presets (gentle / wobbly / stiff / slow):
|
|
402
|
-
|
|
403
|
-
→ **`reference/motion-spring.md`** (Phase 18)
|
|
404
|
-
|
|
405
|
-
For transition family taxonomy (8 families: 3d / blur / cover / destruction / dissolve / distortion / grid / light):
|
|
159
|
+
## Cross-Domain See Also
|
|
406
160
|
|
|
407
|
-
|
|
161
|
+
- Color animation uses OKLCH path: `reference/color.md`
|
|
162
|
+
- Gesture semantics (velocity, pointer capture): `reference/interaction.md`
|
|
163
|
+
- OS-level reduced-motion: `reference/responsive.md`
|
|
164
|
+
- CSS layout transitions: `reference/spatial.md`
|
|
165
|
+
- Typography: `reference/typography.md`
|
|
166
|
+
- UX writing: `reference/ux-writing.md`
|
package/reference/registry.json
CHANGED
|
@@ -625,8 +625,9 @@
|
|
|
625
625
|
{
|
|
626
626
|
"name": "motion",
|
|
627
627
|
"path": "reference/motion.md",
|
|
628
|
-
"type": "
|
|
629
|
-
"description": "
|
|
628
|
+
"type": "domain-index",
|
|
629
|
+
"description": "Phase 45 domain-index: motion navigation - indexes easings, spring, transition-taxonomy, interpolate, advanced, framer-motion-patterns.",
|
|
630
|
+
"phase": 45
|
|
630
631
|
},
|
|
631
632
|
{
|
|
632
633
|
"name": "motion-advanced",
|
|
@@ -797,8 +798,9 @@
|
|
|
797
798
|
{
|
|
798
799
|
"name": "typography",
|
|
799
800
|
"path": "reference/typography.md",
|
|
800
|
-
"type": "
|
|
801
|
-
"description": "
|
|
801
|
+
"type": "domain-index",
|
|
802
|
+
"description": "Phase 45 domain-index: typography navigation - indexes type-scale heuristics, variable-fonts-loading, proportion-systems.",
|
|
803
|
+
"phase": 45
|
|
802
804
|
},
|
|
803
805
|
{
|
|
804
806
|
"name": "user-research",
|
|
@@ -1049,6 +1051,41 @@
|
|
|
1049
1051
|
"type": "meta-rules",
|
|
1050
1052
|
"phase": 42,
|
|
1051
1053
|
"description": "Phase 42 multi-harness skill-placeholder catalogue: the four placeholders ({{command_prefix}}/{{model}}/{{config_file}}/{{ask_instruction}}) + per-harness substitution table + the \\{{...}} escape + the <!-- harness-only: a,b --> block rule. Skills authored once in source/skills/, compiled per-harness by scripts/build-skills.cjs via scripts/lib/build/factory.cjs reading scripts/lib/manifest/harnesses.json."
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
"name": "color",
|
|
1057
|
+
"path": "reference/color.md",
|
|
1058
|
+
"type": "domain-index",
|
|
1059
|
+
"phase": 45,
|
|
1060
|
+
"description": "Phase 45 domain-index: color + contrast navigation - color-theory, palette-catalog, contrast-advanced, style-vocabulary."
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
"name": "spatial",
|
|
1064
|
+
"path": "reference/spatial.md",
|
|
1065
|
+
"type": "domain-index",
|
|
1066
|
+
"phase": 45,
|
|
1067
|
+
"description": "Phase 45 domain-index: layout/spacing/composition - composition, proportion-systems, css-grid-layout, visual-hierarchy-layout, gestalt, image-optimization, data-visualization, surfaces."
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
"name": "interaction",
|
|
1071
|
+
"path": "reference/interaction.md",
|
|
1072
|
+
"type": "domain-index",
|
|
1073
|
+
"phase": 45,
|
|
1074
|
+
"description": "Phase 45 domain-index: interaction + a11y + components - accessibility, component-authoring, form-patterns, information-architecture, onboarding-progressive-disclosure, emotional-design, components/."
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
"name": "responsive",
|
|
1078
|
+
"path": "reference/responsive.md",
|
|
1079
|
+
"type": "domain-index",
|
|
1080
|
+
"phase": 45,
|
|
1081
|
+
"description": "Phase 45 domain-index: responsive + i18n + platforms - i18n, rtl-cjk-cultural, platforms, native-platforms, performance, css-grid-layout."
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
"name": "ux-writing",
|
|
1085
|
+
"path": "reference/ux-writing.md",
|
|
1086
|
+
"type": "domain-index",
|
|
1087
|
+
"phase": 45,
|
|
1088
|
+
"description": "Phase 45 domain-index: UX-writing + voice - brand-voice, style-vocabulary, anti-patterns."
|
|
1052
1089
|
}
|
|
1053
1090
|
]
|
|
1054
1091
|
}
|
|
@@ -4,19 +4,41 @@
|
|
|
4
4
|
"title": "Reference Registry",
|
|
5
5
|
"description": "Typed index of every reference/*.md (and reference/*.json default) in the plugin. Enables agents to query by type instead of grep-hunting import strings. Round-trip enforced: every reference/*.md must appear in entries[], every entry must resolve to an existing file.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"version",
|
|
9
|
+
"generated_at",
|
|
10
|
+
"entries"
|
|
11
|
+
],
|
|
8
12
|
"properties": {
|
|
9
|
-
"$schema": {
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
"$schema": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"version": {
|
|
17
|
+
"const": 1
|
|
18
|
+
},
|
|
19
|
+
"generated_at": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"format": "date-time"
|
|
22
|
+
},
|
|
12
23
|
"entries": {
|
|
13
24
|
"type": "array",
|
|
14
25
|
"items": {
|
|
15
26
|
"type": "object",
|
|
16
|
-
"required": [
|
|
27
|
+
"required": [
|
|
28
|
+
"name",
|
|
29
|
+
"path",
|
|
30
|
+
"type"
|
|
31
|
+
],
|
|
17
32
|
"properties": {
|
|
18
|
-
"name": {
|
|
19
|
-
|
|
33
|
+
"name": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1,
|
|
36
|
+
"pattern": "^[a-z0-9][a-z0-9-._]*$"
|
|
37
|
+
},
|
|
38
|
+
"path": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"minLength": 1
|
|
41
|
+
},
|
|
20
42
|
"type": {
|
|
21
43
|
"type": "string",
|
|
22
44
|
"enum": [
|
|
@@ -41,13 +63,28 @@
|
|
|
41
63
|
"typography",
|
|
42
64
|
"layout",
|
|
43
65
|
"performance",
|
|
44
|
-
"component-spec"
|
|
66
|
+
"component-spec",
|
|
67
|
+
"domain-index"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"tier": {
|
|
71
|
+
"enum": [
|
|
72
|
+
"L0",
|
|
73
|
+
"L1",
|
|
74
|
+
"L2"
|
|
45
75
|
]
|
|
46
76
|
},
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
"phase": {
|
|
78
|
+
"type": "number",
|
|
79
|
+
"description": "Phase that introduced this entry. Numbers are allowed (e.g., 19.6, 27.5, 27.6, 27.7, 28.5) — decimal phases are valid per the long-standing precedent established by Phases 19.6 / 27.5 / 27.6 / 27.7 / 28.5."
|
|
80
|
+
},
|
|
81
|
+
"description": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
},
|
|
84
|
+
"registered_at": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"format": "date-time"
|
|
87
|
+
}
|
|
51
88
|
},
|
|
52
89
|
"additionalProperties": false
|
|
53
90
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Responsive Design - Domain Index
|
|
2
|
+
|
|
3
|
+
This is the domain entry-point for responsive design. Load this file when the
|
|
4
|
+
interface will render in more than one locale, platform, or viewport condition.
|
|
5
|
+
It covers i18n engineering primitives, RTL and CJK cultural adaptation,
|
|
6
|
+
platform-specific conventions, native token bridging, and performance budgets.
|
|
7
|
+
It does not cover the CSS Grid implementation of responsive layouts (see
|
|
8
|
+
`reference/spatial.md` for container queries and `clamp()`); it does not cover
|
|
9
|
+
copy tone for localized content (see `reference/ux-writing.md`).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Fragment Index
|
|
14
|
+
|
|
15
|
+
→ **`reference/i18n.md`** (Phase 28) - use when localizing text: expansion
|
|
16
|
+
budgets (+30-40%), CSS logical props, `Intl.*` APIs, ICU MessageFormat,
|
|
17
|
+
bidi isolation, Unicode normalization, multi-script font stacks
|
|
18
|
+
|
|
19
|
+
→ **`reference/rtl-cjk-cultural.md`** (Phase 28) - use when targeting RTL
|
|
20
|
+
locales or CJK audiences: layout mirroring rules, bidirectional text isolation,
|
|
21
|
+
Arabic/Hebrew/Devanagari rendering, cultural color meanings and imagery norms
|
|
22
|
+
|
|
23
|
+
→ **`reference/platforms.md`** (Phase 19) - use when targeting multiple
|
|
24
|
+
platforms: iOS/Android/web/visionOS/watchOS nav patterns, safe area insets,
|
|
25
|
+
gesture vocabularies, haptics, native typography conventions
|
|
26
|
+
|
|
27
|
+
→ **`reference/native-platforms.md`** (Phase 34.1) - use when bridging design
|
|
28
|
+
tokens to native code: canonical CSS token to SwiftUI Color / Compose Color /
|
|
29
|
+
Flutter ThemeData mapping, precision contract for the round-trip
|
|
30
|
+
|
|
31
|
+
→ **`reference/performance.md`** (Phase 19) - use for any production
|
|
32
|
+
responsive build: Core Web Vitals budgets by project type, JS/font/image
|
|
33
|
+
budgets, React runtime perf rules
|
|
34
|
+
|
|
35
|
+
→ **`reference/css-grid-layout.md`** (Phase 18) - load the container-queries
|
|
36
|
+
and `clamp()` sections only: fluid responsive components, safe-area insets,
|
|
37
|
+
logical CSS props in Grid context
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Rules of Thumb
|
|
42
|
+
|
|
43
|
+
**1. Size containers for the worst-case expansion locale.**
|
|
44
|
+
Russian and Finnish strings expand +40% from an English baseline. Any text
|
|
45
|
+
container designed at English width will overflow in those locales. Build for
|
|
46
|
+
`EN base x 1.4` as the standard layout-budget rule; top-aligned labels absorb
|
|
47
|
+
expansion without horizontal breakage.
|
|
48
|
+
|
|
49
|
+
**2. CSS logical properties are the implementation primitive for RTL.**
|
|
50
|
+
Never use `left`/`right` in a layout that will need to mirror. Replace
|
|
51
|
+
`margin-left` with `margin-inline-start`, `padding-right` with
|
|
52
|
+
`padding-inline-end`, and positioned `left` with `inset-inline-start`. The full
|
|
53
|
+
mapping is in `reference/rtl-cjk-cultural.md`.
|
|
54
|
+
|
|
55
|
+
**3. `prefers-reduced-motion` is a responsive property, not optional.**
|
|
56
|
+
Any animation behind a media query must resolve to `transition: none` or
|
|
57
|
+
`animation-duration: 0.01ms` when the user has set OS-level reduced-motion.
|
|
58
|
+
The CSS reset pattern is in `reference/motion.md`.
|
|
59
|
+
|
|
60
|
+
**4. Native token precision contract: no re-derivation in component code.**
|
|
61
|
+
Color hex values bridge to native at 8-bit channel precision (no rounding).
|
|
62
|
+
Dimension px values bridge as integer dp/pt. The token-bridge round-trip in
|
|
63
|
+
`reference/native-platforms.md` is the source of truth - any re-derivation
|
|
64
|
+
in component code will drift from the canonical value.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Cross-Domain See Also
|
|
69
|
+
|
|
70
|
+
- i18n text expansion affects type container sizing: `reference/typography.md`
|
|
71
|
+
- Touch targets differ from pointer targets: `reference/interaction.md`
|
|
72
|
+
- Layout shifts at breakpoints: `reference/spatial.md`
|
|
73
|
+
- OS-level reduced-motion links to animation rules: `reference/motion.md`
|
|
74
|
+
- Civic multi-language government forms: `reference/domains/civic-patterns.md`
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Spatial - Composition, Grid, and Perceptual Organization
|
|
2
|
+
|
|
3
|
+
Spatial design governs how elements are placed, sized, and related in two-dimensional
|
|
4
|
+
space: composition principles (rule of thirds, focal point, eye-flow), proportion
|
|
5
|
+
derivation (baseline grid, spacing ladder), CSS implementation (Grid, container queries,
|
|
6
|
+
clamp), visual hierarchy, Gestalt grouping, and data presentation. Read this file first,
|
|
7
|
+
then load the specific fragment for the task at hand. Does not cover 3D depth signaling
|
|
8
|
+
via color/shadow as a color decision (see `color.md`) or responsive layout shifts driven
|
|
9
|
+
by locale/platform (see `responsive.md`).
|
|
10
|
+
|
|
11
|
+
## Fragment Index
|
|
12
|
+
|
|
13
|
+
| Fragment | When to load |
|
|
14
|
+
|---|---|
|
|
15
|
+
| [`./composition.md`](./composition.md) | choosing a compositional grid (rule of thirds, root rectangles, Fibonacci), placing a focal point, deciding eye-flow archetype (Z / F / Gutenberg) |
|
|
16
|
+
| [`./proportion-systems.md`](./proportion-systems.md) | deriving the baseline grid unit, spacing ladder, icon sizing, corner radius from a single multiplier (4pt / 8pt / sqrt(2)) |
|
|
17
|
+
| [`./css-grid-layout.md`](./css-grid-layout.md) | implementing CSS Grid templates, subgrid, container queries, `clamp()` fluid type, logical props, anchor positioning |
|
|
18
|
+
| [`./visual-hierarchy-layout.md`](./visual-hierarchy-layout.md) | ordering elements by importance: Z-order, whitespace rules, shadow depth, 24 landing archetypes |
|
|
19
|
+
| [`./gestalt.md`](./gestalt.md) | auditing perceptual grouping: proximity, similarity, continuity, closure, figure/ground - 8 principles with scoring rubrics |
|
|
20
|
+
| [`./image-optimization.md`](./image-optimization.md) | images in layout: format matrix, srcset/sizes math, LQIP/BlurHash, CDN transforms, image budget |
|
|
21
|
+
| [`./data-visualization.md`](./data-visualization.md) | charts/dashboards: 25-type chart-choice matrix, color-blind palettes, axis conventions, UUPM dashboard patterns |
|
|
22
|
+
| [`./surfaces.md`](./surfaces.md) | surface treatments: concentric radius formula, optical alignment, 3-layer shadow system, hit area sizing |
|
|
23
|
+
|
|
24
|
+
## Rules of Thumb
|
|
25
|
+
|
|
26
|
+
1. Place primary CTAs on the rule-of-thirds power points (the 33%/67% intersections), not dead-center. Centered heroes are the intentional exception, not the default.
|
|
27
|
+
2. Choose one baseline unit for the whole product (4pt, 8pt, or sqrt(2)) and author every spacing, sizing, and radius token as a multiple of it. No one-off values.
|
|
28
|
+
3. CSS Grid container queries (`@container`) should replace media queries for component-level layout. Reserve media queries for page-level breakpoints only.
|
|
29
|
+
4. Gestalt proximity rule: related controls 8px apart or less; unrelated groups 32px apart or more. The layout should communicate relationships before the user reads labels.
|
|
30
|
+
5. Choose the chart type before the color palette. The wrong chart type cannot be rescued by a better palette. Use `data-visualization.md` chart-choice matrix first.
|
|
31
|
+
|
|
32
|
+
## See Also
|
|
33
|
+
|
|
34
|
+
- Shadow and elevation as color/depth signal: [`./color.md`](./color.md)
|
|
35
|
+
- Type scale ties into spatial proportion grid: [`./typography.md`](./typography.md)
|
|
36
|
+
- Responsive layout shifts at breakpoints: [`./responsive.md`](./responsive.md)
|
|
37
|
+
- Gestalt grouping informs information architecture: [`./interaction.md`](./interaction.md)
|
|
38
|
+
- Gaming: TV-safe area constraints: [`./domains/gaming-patterns.md`](./domains/gaming-patterns.md)
|
package/reference/typography.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Typography - Scale, Pairing, and Hierarchy
|
|
2
2
|
|
|
3
|
+
This file is the domain index for typography. It covers type-scale construction,
|
|
4
|
+
weight hierarchy, font pairing, and micro-typography. Read `variable-fonts-loading.md`
|
|
5
|
+
when web fonts are in scope. Read `proportion-systems.md` when the full UI grid is
|
|
6
|
+
in scope. Does not cover text-contrast (see `color.md`) or locale text expansion
|
|
7
|
+
(see `responsive.md`, which indexes [`./i18n.md`](./i18n.md) for the per-locale expansion budgets).
|
|
8
|
+
|
|
9
|
+
## Fragment Index
|
|
10
|
+
|
|
11
|
+
| Fragment | When to load |
|
|
12
|
+
|---|---|
|
|
13
|
+
| This file (below) | type scale ratios, sizing tokens, weight hierarchy, font pairings, micro-typography |
|
|
14
|
+
| [`./variable-fonts-loading.md`](./variable-fonts-loading.md) | web fonts, `@font-face`, `font-display`, FOIT/FOUT, variable font axes, subsetting, fallback metrics |
|
|
15
|
+
| [`./proportion-systems.md`](./proportion-systems.md) | 4pt/8pt/sqrt(2) baseline grid, spacing ladder, icon sizing, corner radius derivation |
|
|
16
|
+
|
|
17
|
+
## Rules of Thumb
|
|
18
|
+
|
|
19
|
+
1. A 1.25 (Major Third) or 1.333 (Perfect Fourth) ratio fits 95% of SaaS products; only reach for 1.618 when visual drama is the explicit brief.
|
|
20
|
+
2. Never author `line-height` as a pixel value - always use a unitless multiplier (1.4-1.6 for body, 1.1-1.2 for headings); unitless values scale with user font-size overrides.
|
|
21
|
+
3. Font weight on the web has only 7 meaningful stops (100-700 in 100-steps); any weight not in the font file rounds to the nearest available - check the variable font `wght` range before specifying 450 or 600.
|
|
22
|
+
4. Baseline-grid lock: every spacing and sizing token should be a multiple of the chosen baseline unit; `padding: 12px` next to body at `16/24` on an 8pt grid is a silent proportion break.
|
|
23
|
+
5. For localized UIs, size type containers for +40% expansion (Russian/Finnish worst-case); top-aligned labels are the only label position that absorbs expansion without layout breakage.
|
|
24
|
+
|
|
25
|
+
## See Also
|
|
26
|
+
|
|
27
|
+
- Text contrast and color-blindness checks: [`./color.md`](./color.md)
|
|
28
|
+
- Text expansion in localized UIs: [`./responsive.md`](./responsive.md)
|
|
29
|
+
- Proportion systems tie type to spatial grid: [`./spatial.md`](./spatial.md)
|
|
30
|
+
- Finance number formatting (tabular-nums): [`./domains/finance-patterns.md`](./domains/finance-patterns.md)
|
|
31
|
+
|
|
3
32
|
---
|
|
4
33
|
|
|
5
34
|
## Type Scale Systems
|
|
@@ -35,7 +64,7 @@ Choose a ratio and base size. Common ratios:
|
|
|
35
64
|
|
|
36
65
|
Never create a scale ad-hoc. Pick one ratio, generate the scale, use only values in the scale.
|
|
37
66
|
|
|
38
|
-
**See:** [`./proportion-systems.md`](./proportion-systems.md)
|
|
67
|
+
**See:** [`./proportion-systems.md`](./proportion-systems.md) for how the type scale ties to spacing / sizing / radius scales.
|
|
39
68
|
|
|
40
69
|
---
|
|
41
70
|
|
|
@@ -43,11 +72,11 @@ Never create a scale ad-hoc. Pick one ratio, generate the scale, use only values
|
|
|
43
72
|
|
|
44
73
|
| Context | Line height | Notes |
|
|
45
74
|
|---|---|---|
|
|
46
|
-
| Body text | **1.5
|
|
47
|
-
| Headings | **1.1
|
|
75
|
+
| Body text | **1.5 - 1.75** | More generous = more readable |
|
|
76
|
+
| Headings | **1.1 - 1.3** | Tight heading stacks look intentional |
|
|
48
77
|
| Captions / small text | **1.4** | Smaller text needs more breathing room |
|
|
49
|
-
| Code blocks | **1.6
|
|
50
|
-
| Display / hero | **0.9
|
|
78
|
+
| Code blocks | **1.6 - 1.8** | Line scanning for code |
|
|
79
|
+
| Display / hero | **0.9 - 1.1** | Can go very tight for dramatic effect |
|
|
51
80
|
|
|
52
81
|
---
|
|
53
82
|
|
|
@@ -55,9 +84,9 @@ Never create a scale ad-hoc. Pick one ratio, generate the scale, use only values
|
|
|
55
84
|
|
|
56
85
|
| Context | Characters per line | Notes |
|
|
57
86
|
|---|---|---|
|
|
58
|
-
| Desktop body | **65
|
|
59
|
-
| Mobile body | **35
|
|
60
|
-
| Hero/display | **35
|
|
87
|
+
| Desktop body | **65 - 75 chars** | Optimal reading comfort |
|
|
88
|
+
| Mobile body | **35 - 55 chars** | Narrower viewport forces shorter |
|
|
89
|
+
| Hero/display | **35 - 55 chars** | Headings should never wrap awkwardly |
|
|
61
90
|
| Data/tables | No limit | Tables have own structure |
|
|
62
91
|
|
|
63
92
|
Enforce with `max-width`: `65ch` for body containers works with any font size.
|
|
@@ -68,13 +97,13 @@ Enforce with `max-width`: `65ch` for body containers works with any font size.
|
|
|
68
97
|
|
|
69
98
|
| Role | Weight | Notes |
|
|
70
99
|
|---|---|---|
|
|
71
|
-
| Display headings | **700
|
|
72
|
-
| Page headings | **600
|
|
73
|
-
| Section headings | **500
|
|
100
|
+
| Display headings | **700 - 900** | Bold commands attention |
|
|
101
|
+
| Page headings | **600 - 700** | Strong but not display-level |
|
|
102
|
+
| Section headings | **500 - 600** | Distinguish from body |
|
|
74
103
|
| Body text | **400** | Regular - no emphasis weight |
|
|
75
104
|
| UI labels | **500** | Slightly heavier than body |
|
|
76
105
|
| Captions | **400** | Regular - size reduces emphasis |
|
|
77
|
-
| Monospace code | **400
|
|
106
|
+
| Monospace code | **400 - 500** | |
|
|
78
107
|
|
|
79
108
|
**Rule**: Never use `font-weight: 300` (light) on small text. It becomes illegible below 16px.
|
|
80
109
|
|
|
@@ -127,7 +156,7 @@ Enforce with `max-width`: `65ch` for body containers works with any font size.
|
|
|
127
156
|
|
|
128
157
|
**All caps body text** - reserved for: labels, badges, category markers, short UI labels only. Never for sentences or paragraphs.
|
|
129
158
|
|
|
130
|
-
**Inconsistent tracking** - only use `letter-spacing` intentionally. Positive tracking on uppercase labels is fine. Negative tracking on small body text reduces readability.
|
|
159
|
+
**Inconsistent tracking** - only use `letter-spacing` intentionally. Positive tracking on uppercase labels is fine. Negative tracking on small body text reduces readability.
|
|
131
160
|
|
|
132
161
|
---
|
|
133
162
|
|
|
@@ -136,8 +165,8 @@ Enforce with `max-width`: `65ch` for body containers works with any font size.
|
|
|
136
165
|
| Use case | letter-spacing |
|
|
137
166
|
|---|---|
|
|
138
167
|
| Body text | `0` (default) |
|
|
139
|
-
| Uppercase labels / badges | `0.05em
|
|
140
|
-
| Display headings |
|
|
168
|
+
| Uppercase labels / badges | `0.05em - 0.1em` |
|
|
169
|
+
| Display headings | `-0.02em - 0.01em` |
|
|
141
170
|
| Monospace code | `0` or slight positive |
|
|
142
171
|
|
|
143
172
|
---
|
|
@@ -174,68 +203,19 @@ Test: Can you tell which element is a heading just from the weight/family, witho
|
|
|
174
203
|
|
|
175
204
|
## Brand Archetype Quick Guide
|
|
176
205
|
|
|
177
|
-
Pick the archetype closest to the project brief; use the recommended pairing
|
|
178
|
-
as a starting point (adjust for specific constraints).
|
|
179
|
-
|
|
180
206
|
| Archetype | Character | Recommended Pairing |
|
|
181
207
|
|-----------|-----------|---------------------|
|
|
182
208
|
| SaaS / productivity | clear, neutral, utilitarian | Inter (UI) + Inter (body) - single family |
|
|
183
209
|
| Consumer / editorial | warm, opinionated, expressive | Fraunces or GT Sectra (display) + Inter (body) |
|
|
184
210
|
| Enterprise / finance | authoritative, conservative | IBM Plex Sans (UI) + IBM Plex Serif (body) |
|
|
185
211
|
| Developer tools | technical, efficient | Geist (UI) + Geist Mono (code) |
|
|
186
|
-
| Bold / expressive | high-energy, distinctive |
|
|
187
|
-
|
|
188
|
-
**Selection heuristic:** If the brief uses words like "professional", "trustworthy", "clean" → SaaS or Enterprise. If "warm", "editorial", "narrative" → Consumer. If "bold", "energetic", "distinctive" → Bold. If "technical", "efficient", "fast" → Dev tools.
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## Variable Fonts
|
|
193
|
-
|
|
194
|
-
Variable fonts expose typographic axes that can be animated or set per-context
|
|
195
|
-
via `font-variation-settings`. Prefer variable fonts over static family fallbacks
|
|
196
|
-
when available - one file covers all weights and widths.
|
|
197
|
-
|
|
198
|
-
### Common axes
|
|
199
|
-
|
|
200
|
-
| Axis | Range | Purpose |
|
|
201
|
-
|------|-------|---------|
|
|
202
|
-
| wght | 100–900 | Weight (Thin → Black) |
|
|
203
|
-
| wdth | 50%–150% | Width (Condensed → Extended) |
|
|
204
|
-
| ital | 0 / 1 | Italic toggle (discrete in most) |
|
|
205
|
-
| opsz | font-size value | Optical size (auto-applies when `font-optical-sizing: auto`) |
|
|
206
|
-
|
|
207
|
-
### @font-face format
|
|
208
|
-
|
|
209
|
-
```css
|
|
210
|
-
@font-face {
|
|
211
|
-
font-family: 'InterVariable';
|
|
212
|
-
src: url('/fonts/InterVariable.woff2') format('woff2-variations');
|
|
213
|
-
font-weight: 100 900;
|
|
214
|
-
font-style: normal;
|
|
215
|
-
}
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### Usage via font-variation-settings
|
|
219
|
-
|
|
220
|
-
```css
|
|
221
|
-
.heading { font-variation-settings: "wght" 700, "opsz" 32; }
|
|
222
|
-
.body { font-variation-settings: "wght" 400; }
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Fallback strategy
|
|
226
|
-
|
|
227
|
-
Always include a non-variable fallback of the same family in the font stack:
|
|
228
|
-
|
|
229
|
-
```css
|
|
230
|
-
font-family: 'InterVariable', 'Inter', -apple-system, system-ui, sans-serif;
|
|
231
|
-
```
|
|
212
|
+
| Bold / expressive | high-energy, distinctive | Sohne or Mona Sans (display) + Inter (body) |
|
|
232
213
|
|
|
233
|
-
**
|
|
214
|
+
**Selection heuristic:** If the brief uses words like "professional", "trustworthy", "clean" use SaaS or Enterprise. If "warm", "editorial", "narrative" use Consumer. If "bold", "energetic", "distinctive" use Bold. If "technical", "efficient", "fast" use Dev tools.
|
|
234
215
|
|
|
235
216
|
---
|
|
236
217
|
|
|
237
218
|
## Micro-Typography
|
|
238
|
-
Source: jakubkrehel/make-interfaces-feel-better (MIT) - typography.md
|
|
239
219
|
|
|
240
220
|
### text-wrap
|
|
241
221
|
|
|
@@ -254,7 +234,7 @@ Apply antialiasing at root level only:
|
|
|
254
234
|
-moz-osx-font-smoothing: grayscale;
|
|
255
235
|
}
|
|
256
236
|
```
|
|
257
|
-
Never apply per-element - this creates inconsistency within a single text block
|
|
237
|
+
Never apply per-element - this creates inconsistency within a single text block.
|
|
258
238
|
|
|
259
239
|
### Tabular numerals
|
|
260
240
|
|
|
@@ -262,52 +242,4 @@ Use tabular-nums on any surface where numbers change dynamically or need to alig
|
|
|
262
242
|
```css
|
|
263
243
|
.counter, .price, .timer, .table-cell { font-variant-numeric: tabular-nums; }
|
|
264
244
|
```
|
|
265
|
-
Proportional numerals (the default) cause text to shift width when numbers change, creating
|
|
266
|
-
|
|
267
|
-
## Font Pairings Catalog
|
|
268
|
-
Source: nextlevelbuilder/ui-ux-pro-max-skill (MIT) - data/typography.csv
|
|
269
|
-
|
|
270
|
-
57 professionally curated pairings grouped by use-case vertical. For font loading, see `reference/data/google-fonts.csv` for the full 1923-font reference.
|
|
271
|
-
|
|
272
|
-
### SaaS / Productivity
|
|
273
|
-
- **Inter + Inter** (mono weight hierarchy) - The "safe default" for app UIs. Use regular (400) for body, medium (500) for labels, semibold (600) for headings. Consistent x-height, excellent at small sizes.
|
|
274
|
-
- **Inter + JetBrains Mono** - For dev tools and dashboards with code display. JetBrains Mono has excellent legibility at 12-14px.
|
|
275
|
-
- **Geist Sans + Geist Mono** - Vercel's pair; clean, modern, designed together.
|
|
276
|
-
- **Outfit + DM Mono** - Friendly SaaS feel with clear code fallback.
|
|
277
|
-
|
|
278
|
-
### Consumer / Marketing
|
|
279
|
-
- **Satoshi + Cabinet Grotesk** - High-energy, modern consumer feel.
|
|
280
|
-
- **Plus Jakarta Sans + Syne** - Playful but legible; works for creative consumer apps.
|
|
281
|
-
- **DM Sans + DM Serif Display** - Classic pairing; editorial headers, clean body.
|
|
282
|
-
- **Nunito + Source Code Pro** - Approachable and friendly.
|
|
283
|
-
|
|
284
|
-
### Finance / Enterprise
|
|
285
|
-
- **IBM Plex Sans + IBM Plex Mono** - Authoritative, systematic, designed for data-heavy interfaces.
|
|
286
|
-
- **Source Sans 3 + Source Code Pro** - Adobe's workhorse pair; widely trusted.
|
|
287
|
-
- **Lato + Roboto Mono** - Clean, neutral enterprise pair.
|
|
288
|
-
|
|
289
|
-
### Editorial / Publishing
|
|
290
|
-
- **Playfair Display + Source Serif 4** - High contrast serif headers with readable body serif.
|
|
291
|
-
- **Cormorant Garamond + Proza Libre** - Elegant luxury/editorial tone.
|
|
292
|
-
- **Libre Baskerville + Libre Franklin** - Free-license editorial pair.
|
|
293
|
-
- **EB Garamond + Lato** - Classic print feel with modern body.
|
|
294
|
-
|
|
295
|
-
### Wellness / Health
|
|
296
|
-
- **Nunito + Nunito Sans** - Soft, approachable, consistent x-height.
|
|
297
|
-
- **Quicksand + Work Sans** - Rounded, friendly, healthcare-appropriate.
|
|
298
|
-
- **Raleway + Open Sans** - Clean and welcoming.
|
|
299
|
-
|
|
300
|
-
### Dev Tools
|
|
301
|
-
- **JetBrains Mono + Inter** - Code-first, UI-second; natural for developer tools.
|
|
302
|
-
- **Fira Code + Fira Sans** - Cohesive family; ligatures available.
|
|
303
|
-
- **Cascadia Code + Segoe UI** - Microsoft's modern dev pair.
|
|
304
|
-
|
|
305
|
-
### Luxury / Fashion
|
|
306
|
-
- **Cormorant + Montserrat** - High contrast serif + geometric sans; classic luxury.
|
|
307
|
-
- **Bodoni Moda + Jost** - Fashion editorial feel.
|
|
308
|
-
- **Playfair Display + Raleway** - Elegant header + clean body.
|
|
309
|
-
|
|
310
|
-
### Gaming / Entertainment
|
|
311
|
-
- **Syne + DM Sans** - Bold, energetic headers; clean readable body.
|
|
312
|
-
- **Bebas Neue + Open Sans** - Impact headlines; neutral body.
|
|
313
|
-
- **Exo 2 + Roboto** - Futuristic but readable.
|
|
245
|
+
Proportional numerals (the default) cause text to shift width when numbers change, creating jitter in timers and prices. Exception: Inter's `1` character widens slightly with tabular-nums - test at your numeric composition before committing.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# UX Writing - Domain Index
|
|
2
|
+
|
|
3
|
+
This is the domain entry-point for UX writing. Load this file when the task
|
|
4
|
+
involves voice, tone, or the copy standards that govern text a user reads in
|
|
5
|
+
the product: button labels, error messages, empty states, onboarding copy, and
|
|
6
|
+
microcopy. It does not cover the engineering side of localization (see
|
|
7
|
+
`reference/responsive.md` for string expansion budgets and `Intl.*` APIs); it
|
|
8
|
+
does not cover label position in forms or information architecture (see
|
|
9
|
+
`reference/interaction.md`).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Fragment Index
|
|
14
|
+
|
|
15
|
+
→ **`reference/brand-voice.md`** (Phase 24) - use when establishing or
|
|
16
|
+
auditing tone: 6 voice axes (Formal-Casual, Serious-Playful, etc.), 12
|
|
17
|
+
archetypes, tone-by-context matrix, industry-context palettes
|
|
18
|
+
|
|
19
|
+
→ **`reference/style-vocabulary.md`** (Phase 24) - use when confirming an
|
|
20
|
+
aesthetic direction has a compatible voice register: the `Avoid For` column
|
|
21
|
+
cross-checks brand fit; `Best For` confirms product-type alignment
|
|
22
|
+
|
|
23
|
+
→ **`reference/anti-patterns.md`** - use when auditing existing copy: the
|
|
24
|
+
BAN/SLOP grep patterns surface copy violations (AI-tells, filler phrases)
|
|
25
|
+
alongside visual ones
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Rules of Thumb
|
|
30
|
+
|
|
31
|
+
**1. Voice axes are independent from archetypes.**
|
|
32
|
+
Pick a position on each of the 6 axes first (Formal-Casual, Serious-Playful,
|
|
33
|
+
Authoritative-Supportive, and so on), then layer an archetype on top. The
|
|
34
|
+
archetype does not determine the axis position - they are orthogonal dimensions
|
|
35
|
+
in `reference/brand-voice.md`.
|
|
36
|
+
|
|
37
|
+
**2. Never use placeholder text as the sole label for a form field.**
|
|
38
|
+
It disappears on focus, fails WCAG 1.3.5, and collapses under translation.
|
|
39
|
+
Top-aligned labels are the only position that absorbs localization expansion
|
|
40
|
+
without breaking layout.
|
|
41
|
+
|
|
42
|
+
**3. Error messages follow a three-clause structure: what happened, why, what
|
|
43
|
+
to do.**
|
|
44
|
+
State the event in past tense, explain the cause in one clause, give a present
|
|
45
|
+
tense imperative for recovery. No tech jargon. Never blame the user.
|
|
46
|
+
|
|
47
|
+
**4. Shift toward supportive tone during error, empty-state, and onboarding
|
|
48
|
+
moments.**
|
|
49
|
+
Even a formally-voiced product should move on the axis toward supportive when
|
|
50
|
+
the user is at risk of abandonment. The per-context tone matrix in
|
|
51
|
+
`reference/brand-voice.md` provides the exact adjustment.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Cross-Domain See Also
|
|
56
|
+
|
|
57
|
+
- String expansion budgets constrain copy length: `reference/responsive.md`
|
|
58
|
+
- Error copy paired with form patterns: `reference/interaction.md`
|
|
59
|
+
- Empty-state copy pairs with onboarding pattern: `reference/interaction.md`
|
|
60
|
+
- Style direction voice register cross-check: `reference/style-vocabulary.md`
|