@fracazo/design-system 0.2.1 → 0.7.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.
Files changed (46) hide show
  1. package/DESIGN.md +11 -1
  2. package/README.md +78 -13
  3. package/css/motion.css +155 -0
  4. package/css/roles.css +3 -0
  5. package/dist/guardrails/eslint.d.ts +72 -5
  6. package/dist/guardrails/eslint.js +197 -29
  7. package/dist/guardrails/init.d.ts +2 -0
  8. package/dist/guardrails/init.js +65 -0
  9. package/dist/guardrails/intake.d.ts +2 -0
  10. package/dist/guardrails/intake.js +131 -0
  11. package/dist/src/index.d.ts +1 -0
  12. package/dist/src/index.js +1 -0
  13. package/dist/src/ui/offer-card.d.ts +52 -0
  14. package/dist/src/ui/offer-card.js +7 -0
  15. package/package.json +8 -3
  16. package/skills/product-design/SKILL.md +142 -0
  17. package/skills/product-design/coverage-gaps.md +41 -0
  18. package/skills/product-design/exemplars/calm-the-offering-cards.md +33 -0
  19. package/skills/product-design/exemplars/clamp-drift-to-named-roles.md +37 -0
  20. package/skills/product-design/exemplars/concentric-radii-and-button-optics.md +36 -0
  21. package/skills/product-design/exemplars/dialog-close-focus-visible.md +36 -0
  22. package/skills/product-design/exemplars/hero-glow-seam.md +34 -0
  23. package/skills/product-design/intake/2026-09-07.md +413 -0
  24. package/skills/product-design/references/components.md +43 -0
  25. package/skills/product-design/references/copy.md +25 -0
  26. package/skills/product-design/references/intake.md +66 -0
  27. package/skills/product-design/references/motion.md +22 -0
  28. package/skills/product-design/references/rules.md +319 -0
  29. package/skills/product-design/references/surfaces.md +50 -0
  30. package/skills/product-design/references/tokens.md +54 -0
  31. package/skills/product-design/references/type-and-space.md +42 -0
  32. package/skills/product-design/references/verification.md +35 -0
  33. package/template/CLAUDE.md +47 -0
  34. package/template/README.md +16 -0
  35. package/template/eslint.config.mjs +20 -0
  36. package/template/gitignore +44 -0
  37. package/template/next.config.ts +7 -0
  38. package/template/package.json +40 -0
  39. package/template/pnpm-workspace.yaml +14 -0
  40. package/template/postcss.config.mjs +7 -0
  41. package/template/src/app/globals.css +66 -0
  42. package/template/src/app/layout.tsx +55 -0
  43. package/template/src/app/page.tsx +59 -0
  44. package/template/src/components/ThemeSync.tsx +21 -0
  45. package/template/src/system/brands/starter.css +143 -0
  46. package/template/tsconfig.json +34 -0
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: product-design
3
+ description: >-
4
+ Single entry point for product design and user-facing implementation in a
5
+ product built on @fracazo/design-system. Use whenever work changes what a
6
+ reader sees, understands, chooses or does: shaping a flow, building or
7
+ restyling a page or component, reviewing a route, screenshot or diff,
8
+ improving copy, hierarchy, layout, interaction, accessibility, responsive
9
+ behaviour or loading, empty, error and destructive states. Trigger on
10
+ design, UX, UI, layout, styling, tokens, colour, type, spacing, motion,
11
+ copy, polish, audit, review, accessibility, dark mode, mobile. Not for
12
+ backend-only work, telemetry, generated files, or tests with no shipped UI.
13
+ ---
14
+
15
+ # Product design on @fracazo/design-system
16
+
17
+ Make the surface correct for the reader, the product and the system. Working
18
+ code is not enough: choose the right composition, spend emphasis once, cover
19
+ the states the product can really enter, and verify the rendered result in
20
+ both themes. The stylesheet and the lint do the visual work; this skill
21
+ carries the judgment and the reasons.
22
+
23
+ ## Operating contract
24
+
25
+ - **Start with the reader's job, not the pixels.** Who is reading, on what
26
+ device, under what pressure, and what they must decide or do here.
27
+ - **Name the surface scope first.** Engagement (the product) or conversion
28
+ (landing, guides). Budgets, imagery and motion rules differ. See
29
+ `references/surfaces.md`.
30
+ - **Use evidence, not taste.** Trace a decision to a rule in
31
+ `references/rules.md`, a section of `DESIGN.md`, a component's intent
32
+ block, or an exemplar. Shipped code proves what exists, not that it is
33
+ right.
34
+ - **Decide before decorating.** Composition, component choice and states
35
+ before colour, radius or copy.
36
+ - **Spend emphasis once.** One focal relationship per screen. When a surface
37
+ shouts, remove signals; never add a louder one.
38
+ - **Values live in tokens.** Never a colour, radius or fluid size literal in a
39
+ className. A missing value is a proposal for the design-system repo.
40
+ - **Verify the real surface.** Source inspection establishes behaviour; a
41
+ rendered page in light and dark establishes quality. Token work runs the
42
+ product's snapshot compare.
43
+ - **Keep one entry point.** Load this file; route to the references below.
44
+ Do not paste their content into answers; cite the rule ID or section.
45
+
46
+ ## Request modes
47
+
48
+ Resolve the mode from the verb before acting. Use the narrowest mode the
49
+ verb supports. A URL, screenshot or route sets scope; it does not authorise
50
+ edits.
51
+
52
+ | Mode | Typical request | Required behaviour |
53
+ |---|---|---|
54
+ | Shape | "Design this flow", "how should this work?" | Frame reader, job, evidence; compare material alternatives; define flow, states, acceptance criteria and open decisions. No edits unless asked. |
55
+ | Implement | "Build", "fix", "improve", "make it compliant" | Resolve material decisions, then the smallest coherent end-to-end change. Do not absorb unrelated findings. |
56
+ | Review | "Audit", "critique", "what's wrong?" | Inspect source and rendered evidence; report prioritised findings with rule IDs. No edits unless asked. |
57
+ | Copy | "Fix the copy", "rewrite this error" | Edit user-facing language and accessible names only. Report structural blockers; do not widen scope. |
58
+ | Harden | "Polish", "production-ready", "edge cases" | Keep the settled direction; fix state, resilience, responsive, accessibility and finish defects. |
59
+
60
+ A material decision changes the reader's task, default, consequence,
61
+ navigation, interaction surface or reachable states. Token substitution and
62
+ established component swaps are not material.
63
+
64
+ ## Decision authority
65
+
66
+ Resolve conflicts in this order.
67
+
68
+ 1. The user's explicit goal and constraints.
69
+ 2. Verified product behaviour and system truth (what the tokens and
70
+ components actually do).
71
+ 3. The product's CLAUDE.md, then this skill's `references/rules.md`,
72
+ `DESIGN.md`, `css/roles.css` and the component intent blocks.
73
+ 4. Exemplars with stable evidence (`exemplars/`).
74
+ 5. Verified adjacent shipped patterns in the same product area.
75
+ 6. General interface heuristics.
76
+
77
+ ## Workflow
78
+
79
+ 1. **Set scope and mode.** Name the product, the route or component, the
80
+ surface scope and the mode.
81
+ 2. **Load product context.** The product's CLAUDE.md design section, the
82
+ brand file, the product chapter in `DESIGN.md`, and the code that
83
+ decides what the surface can show.
84
+ 3. **Model the decision** (Shape, Implement, Harden, full Review). Reader,
85
+ job, current behaviour, desired outcome, success signal, non-goals,
86
+ consequence, reversibility, open decisions. Keep it compact.
87
+ 4. **Map the surface and states.** Entry points, regions, overlays,
88
+ transitions, exits. Only reachable states: loading, empty, populated,
89
+ validation, error, disabled, optimistic, destructive, both themes,
90
+ 360px and 1280px.
91
+ 5. **Load the routed references.**
92
+
93
+ | Need | Load |
94
+ |---|---|
95
+ | Any styling or token decision | `references/tokens.md` |
96
+ | Sizes, radius, spacing, rhythm | `references/type-and-space.md` |
97
+ | Hover, entrance, transitions, reduced motion | `references/motion.md` |
98
+ | Which component, house patterns | `references/components.md` + the component's intent block |
99
+ | Copy, labels, errors, English variant | `references/copy.md` |
100
+ | Which surface, budgets, imagery | `references/surfaces.md` |
101
+ | Any rule by ID, lint status, examples | `references/rules.md` |
102
+ | Before claiming zero visual change | `references/verification.md` |
103
+ | Running or judging an intake packet | `references/intake.md` |
104
+
105
+ 6. **Decide, then implement.** For each non-mechanical change be able to
106
+ say: what reader problem it solves, why this component, what consequence
107
+ the surface must communicate, which rule or exemplar supports it, and
108
+ what the smallest coherent change is.
109
+ 7. **Verify.** Lint (`pnpm lint`), typecheck, both themes, compact and wide
110
+ viewports, keyboard order and focus, every materially changed state, long
111
+ content. Token work: snapshot compare, delta stated.
112
+
113
+ ## Review output
114
+
115
+ Lead with findings, ordered by reader impact.
116
+
117
+ - **P0** blocks the primary task, severe accessibility failure, or harm the
118
+ reader cannot undo.
119
+ - **P1** likely task failure, misleading consequence, missing critical
120
+ state, major responsive or accessibility defect.
121
+ - **P2** meaningful friction, weak hierarchy, inconsistency, recoverability.
122
+ - **P3** minor craft.
123
+
124
+ Each finding: location (file and line, or rendered), verification status
125
+ (seen rendered, inferred from source), rule ID or source, reader
126
+ consequence, smallest concrete fix.
127
+
128
+ ## Skill integrity
129
+
130
+ - Add or change a rule only after the same correction has recurred and a
131
+ human has accepted it. One screenshot, one file or one review comment is
132
+ never a rule by itself.
133
+ - Record scope, rule, why, exceptions, source and a bad and good example
134
+ (`references/rules.md` format).
135
+ - Prefer the narrowest destination: a token or contract entry, a lint rule,
136
+ a rule record, an exemplar, or a coverage gap. Deterministic checks stay
137
+ mechanical; judgment stays in prose with its evidence.
138
+ - New evidence enters through the intake loop (`references/intake.md`):
139
+ `ds-intake` collects, the agent proposes in the packet, a human reviews
140
+ and accepts.
141
+ - Keep `coverage-gaps.md` honest. A missing rule is not a licence to invent
142
+ one; it is a decision to raise.
@@ -0,0 +1,41 @@
1
+ # Coverage gaps
2
+
3
+ Decisions we do not have a standard for yet, and rules that exist in prose
4
+ but could be code. A gap is a decision to raise, not a licence to invent.
5
+
6
+ ## Lint candidates (checkable by code, not written)
7
+
8
+ Shipped in 0.4.0 as `design-system/*` rules: no-colour-literal,
9
+ no-arbitrary-clamp, no-dark-pairs, no-radius-literal, no-stock-palette,
10
+ focus-visible, on-dark-ramp, no-em-dash. Still candidates:
11
+
12
+ - A `className` on a package component that overrides its colour, radius or
13
+ shadow (layout classes allowed). Needs the imported component names.
14
+ - rule/no-dark-pairs, second form: a `dark:` token utility beside its light
15
+ twin (`bg-band dark:bg-dark`), which usually means a missing token.
16
+ - rule/voice-bans as a word list over string literals in JSX.
17
+ - Warnings to turn into errors once each product is clean: no-stock-palette
18
+ (BirthGuide 48, birthplans 5), focus-visible (24, 2), no-em-dash (47, 23).
19
+
20
+ ## Missing decisions
21
+
22
+ - Loading, empty and error state patterns for engagement surfaces beyond
23
+ optimistic writes: no written standard; each product improvised.
24
+ - Destructive action wording and confirmation shape: not standardised
25
+ (current usage: the questionnaire discard flow, plan deletion).
26
+ - Toast or inline confirmation after a save: no standard.
27
+ - Form validation timing (on blur, on submit) and error placement: follow
28
+ the package's FormMessage, but no written rule.
29
+ - A house table treatment: none; the price tracker and calculators each
30
+ built their own.
31
+ - Illustration style for conversion surfaces: the brand spec's guidance
32
+ predates the warm palette and names colours that are not in production.
33
+ - birthplans.app type-role pass: fourteen clamp literals await convergence
34
+ before its fluid-type lint can switch on.
35
+ - Whether a product may ship a manual theme toggle: today, none do, by
36
+ decision; not recorded as a rule.
37
+
38
+ ## Evals
39
+
40
+ None yet. When the exemplars reach ten, build before and after fixtures
41
+ from them and hold two out.
@@ -0,0 +1,33 @@
1
+ # Exemplar: calm the offering cards
2
+
3
+ Status: accepted
4
+ Product: BirthGuide, landing hero offering pair
5
+ Source: BirthGuide commit "feat(landing): calm the offering cards down"
6
+ Rules: rule/one-emphasis-signal, rule/concentric-radii, rule/semantic-first
7
+
8
+ ## Decision
9
+
10
+ The two hero cards carried four emphasis signals at once: a tinted border,
11
+ a heavy drop shadow, a bold uppercase chip and an accent CTA. Cut to the
12
+ chip and the CTA. Both cards moved onto the same hairline and the same soft
13
+ shadow, and onto the treatment the testimonial cards already used
14
+ (`rounded-20 p-7 shadow-warm-sm`). Type and ornament came down with it:
15
+ icon tiles 54px to 40px, title capped at 24px, the accent semibold tagline
16
+ became a muted caption, accent ticks became muted dots. The comparison band
17
+ took the same surface so the two pairs still read as siblings.
18
+
19
+ ## Why it matters
20
+
21
+ Emphasis is a budget. When everything on a card is loud, nothing is. The
22
+ fix was subtraction and reuse of an existing surface, not a new style.
23
+
24
+ ## Repeat
25
+
26
+ - Count the signals on a surface before styling it. If more than one, remove.
27
+ - Borrow the surface an adjacent component already uses before inventing one.
28
+ - Bring siblings along so a calmer card does not look like the odd one out.
29
+
30
+ ## Avoid
31
+
32
+ - Answering "this card does not stand out" with a stronger border or shadow.
33
+ - A new radius, shadow or tint for one card.
@@ -0,0 +1,37 @@
1
+ # Exemplar: converge near-miss clamp drift onto named roles
2
+
3
+ Status: accepted
4
+ Product: BirthGuide landing, then the package's type roles
5
+ Source: BirthGuide commits "refactor(design): name the fluid type and band rhythm tokens", "fix(landing): converge near-miss clamp drift onto the named tokens", "feat(lint): guard arbitrary fluid type sizes in className"
6
+ Rules: rule/no-arbitrary-clamp
7
+
8
+ ## Decision
9
+
10
+ A typography audit found five bespoke h1 clamps, eight section-title
11
+ clamps and seven lede clamps, most within a pixel or two of each other.
12
+ The exact current hero scale became `text-display` (byte-identical, with
13
+ its 0.9 line-height companion); section titles and ledes converged onto
14
+ `text-section-title` and `text-lede`, with two approved rewraps checked
15
+ from renders (lede cap 20px to 19px, guides gap 48px to 52px). The final
16
+ CTA kept its bespoke 62px clamp by decision, as did the benched sections
17
+ and the mobile-link h1; each carries an inline disable with the reason.
18
+ Then the lint rule went on so no new clamp literal lands.
19
+
20
+ ## Why it matters
21
+
22
+ Near-miss sizes are invisible drift: nobody can say which of eight almost
23
+ identical clamps is the intended one. Naming the role settles it, and the
24
+ lint keeps it settled. The deliberate one-offs stay visible in review
25
+ because the disable states why.
26
+
27
+ ## Repeat
28
+
29
+ - Name the role at the exact current value first (zero change), then
30
+ converge the near misses in a separate, render-reviewed step.
31
+ - Turn the lint on only after the codebase is clean or every exception is
32
+ disabled with a reason.
33
+
34
+ ## Avoid
35
+
36
+ - Converging by eye in one pass with the rename.
37
+ - Silencing the rule file-wide.
@@ -0,0 +1,36 @@
1
+ # Exemplar: craft pass, concentric radii and button optics
2
+
3
+ Status: accepted
4
+ Product: BirthGuide, then the package's Button
5
+ Source: BirthGuide commits "feat(design): craft pass tier 1: tabular numerals, concentric radii, button optics", "feat(ui): move button primitive from pill to size-scaled rounded-rect" (SPEC_021)
6
+ Rules: rule/concentric-radii, rule/no-radius-literal
7
+
8
+ ## Decision
9
+
10
+ Exact-token radius renames first (`rounded-[26px]` to `4xl`,
11
+ `rounded-[14px]` to `xl`, `rounded-[10px]` to `lg`), zero rendering change.
12
+ Then concentric corners where a rounded child meets a rounded parent, each
13
+ landing on a named token. Tabular numerals on five column surfaces only;
14
+ headline figures stayed proportional. Buttons moved from pills to rounded
15
+ rectangles on a size-scaled corner ladder so a flush button can go
16
+ concentric with its container, and only the icon side of a button tightens
17
+ so icon-plus-text reads centred (the primitive wraps bare text in a span so
18
+ CSS can tell which side the icon is on).
19
+
20
+ ## Why it matters
21
+
22
+ The snapshot harness compared identical on all 311 covered keys, which
23
+ proved no incidental drift; the intended changes sat below the tool's
24
+ resolution and were reviewed as source diff plus live probes. Craft work
25
+ and refactor work were separated so each could be verified its own way.
26
+
27
+ ## Repeat
28
+
29
+ - Split exact renames (identical snapshot) from intended changes (reviewed
30
+ renders), even inside one spec.
31
+ - Apply the concentric formula only where corners meet.
32
+
33
+ ## Avoid
34
+
35
+ - Tabular numerals everywhere; they are for columns.
36
+ - A pill button inside a rounded card; the corners can never be concentric.
@@ -0,0 +1,36 @@
1
+ # Exemplar: dialog close ring only for keyboard users
2
+
3
+ Status: accepted
4
+ Product: BirthGuide, now the package's Dialog
5
+ Source: BirthGuide commit "fix(ui): show the dialog close ring only for keyboard users"
6
+ Rules: rule/focus-visible
7
+
8
+ ## Decision
9
+
10
+ Three PDF-preview modals showed a focus ring on their close button when
11
+ opened with a mouse; the birth-webpage preview did not. The modals were the
12
+ same component. Radix autofocuses the first focusable element on open, and
13
+ the close button carried `focus:ring-2`, so the ring painted wherever the
14
+ dialog body had no controls of its own. Switching to `focus-visible:`
15
+ removed the ring for pointer users on every dialog and kept it for
16
+ keyboard users. Verified both ways: after a click the computed box-shadow
17
+ was none; after Shift+Tab the button matched `:focus-visible` and rendered
18
+ the brand ring.
19
+
20
+ ## Why it matters
21
+
22
+ The reader saw a mystery highlight on a button they had not touched. It
23
+ looked like a bug and it was one, in the shadcn default. The comment above
24
+ the element records the reason because `shadcn add dialog` reverts it.
25
+
26
+ ## Repeat
27
+
28
+ - Measure before changing: the two modals were compared property by
29
+ property and only the focused element differed.
30
+ - Verify accessibility fixes in both directions, pointer and keyboard.
31
+ - Write the reason next to a deliberate deviation from a generator's default.
32
+
33
+ ## Avoid
34
+
35
+ - Fixing one modal. The component is shared; fix it once, upstream.
36
+ - Removing the ring for everyone.
@@ -0,0 +1,34 @@
1
+ # Exemplar: blend the hero glow into the next section
2
+
3
+ Status: accepted
4
+ Product: BirthGuide, landing hero to curriculum boundary
5
+ Source: BirthGuide commit "fix(landing): blend the hero glow into the curriculum section"
6
+ Rules: rule/no-clipped-ambient
7
+
8
+ ## Decision
9
+
10
+ The hero's ambient glow layer kept `overflow-hidden` because its blobs sit
11
+ past the left and right edges, but the same clip sat at `bottom-0` and cut
12
+ the second blob flat at the hero's last pixel. Measured at 1280x800, the
13
+ boundary carried a luminance step of 16.99 in dark and 5.63 in light,
14
+ exactly on the row where the sections meet. Three changes together: the
15
+ layer extends 280px past the bottom (blob offset plus blur), a mask
16
+ dissolves the overhang across that distance, and the next section takes
17
+ `relative z-10` so the glow paints behind its content.
18
+
19
+ ## Why it matters
20
+
21
+ A hard horizontal seam between sections is the kind of defect nobody can
22
+ name but everyone feels. It was invisible in source and obvious once
23
+ measured on the rendered page.
24
+
25
+ ## Repeat
26
+
27
+ - Verify ambient effects rendered, at the seam, in both themes; measure the
28
+ luminance step if unsure.
29
+ - Extend the clip past blob plus blur, then mask; do not just remove the clip.
30
+ - Give the following section a stacking context so the overhang stays behind.
31
+
32
+ ## Avoid
33
+
34
+ - Shrinking or moving the blob to dodge the clip; the composition changes.