@mohammadhprp/system-prompt 0.12.2 → 0.12.4

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 (162) hide show
  1. package/framework/commands/README.md +1 -1
  2. package/framework/commands/review.md +1 -1
  3. package/framework/mcps/README.md +0 -1
  4. package/framework/plugins/ponytail/README.md +0 -1
  5. package/framework/plugins/ponytail/capabilities.md +1 -1
  6. package/framework/references/standards/api.md +0 -1
  7. package/framework/references/standards/architecture.md +0 -1
  8. package/framework/references/standards/database.md +0 -1
  9. package/framework/references/standards/debugging.md +0 -1
  10. package/framework/references/standards/documentation.md +0 -1
  11. package/framework/references/standards/logging.md +0 -1
  12. package/framework/references/standards/naming.md +0 -1
  13. package/framework/references/standards/observability.md +0 -1
  14. package/framework/references/standards/performance.md +0 -1
  15. package/framework/references/standards/pull-requests.md +0 -1
  16. package/framework/references/standards/security.md +0 -1
  17. package/framework/references/standards/testing.md +0 -1
  18. package/framework/skills/README.md +16 -12
  19. package/framework/skills/architect/SKILL.md +83 -0
  20. package/framework/skills/architect/examples.md +5 -0
  21. package/framework/skills/architect/references/design-red-flags.md +33 -0
  22. package/framework/skills/architect/references/rationale-template.md +35 -0
  23. package/framework/skills/architect/references/runner-prompt.md +20 -0
  24. package/framework/skills/arena/SKILL.md +71 -0
  25. package/framework/skills/arena/examples.md +5 -0
  26. package/framework/skills/bro/SKILL.md +7 -0
  27. package/framework/skills/bro/examples.md +5 -0
  28. package/framework/skills/changelog/SKILL.md +41 -0
  29. package/framework/skills/changelog/examples.md +5 -0
  30. package/framework/skills/commit/SKILL.md +28 -0
  31. package/framework/skills/commit/examples.md +5 -0
  32. package/framework/skills/how/SKILL.md +135 -0
  33. package/framework/skills/how/examples.md +5 -0
  34. package/framework/skills/how/references/critic-prompt.md +59 -0
  35. package/framework/skills/how/references/critique-rubric.md +58 -0
  36. package/framework/skills/how/references/explainer-prompt.md +55 -0
  37. package/framework/skills/how/references/explorer-prompt.md +52 -0
  38. package/framework/skills/improve/SKILL.md +1 -3
  39. package/framework/skills/improve/examples.md +1 -1
  40. package/framework/skills/laravel-best-practices/SKILL.md +56 -216
  41. package/framework/skills/laravel-best-practices/references/architecture.md +1 -1
  42. package/framework/skills/laravel-best-practices/references/checklist.md +139 -0
  43. package/framework/skills/laravel-best-practices/references/eloquent.md +4 -2
  44. package/framework/skills/laravel-best-practices/references/infer-conventions.md +97 -0
  45. package/framework/skills/laravel-best-practices/references/pest-testing.md +47 -18
  46. package/framework/skills/laravel-best-practices/references/security.md +1 -1
  47. package/framework/skills/laravel-best-practices/references/style.md +1 -1
  48. package/framework/skills/laravel-best-practices/references/tailwindcss.md +0 -1
  49. package/framework/skills/merge-request/SKILL.md +40 -0
  50. package/framework/skills/merge-request/examples.md +5 -0
  51. package/framework/skills/pull-request/SKILL.md +31 -0
  52. package/framework/skills/pull-request/examples.md +5 -0
  53. package/framework/skills/release/SKILL.md +30 -0
  54. package/framework/skills/release/examples.md +5 -0
  55. package/framework/skills/review/SKILL.md +18 -0
  56. package/framework/skills/review/examples.md +5 -0
  57. package/framework/skills/tdd/SKILL.md +44 -0
  58. package/framework/skills/tdd/examples.md +5 -0
  59. package/framework/skills/unslop/SKILL.md +81 -0
  60. package/framework/skills/unslop/examples.md +5 -0
  61. package/framework/skills/why/SKILL.md +230 -0
  62. package/framework/skills/why/examples.md +5 -0
  63. package/framework/skills/why/references/epistemics.md +144 -0
  64. package/framework/skills/why/references/investigator-prompt.md +103 -0
  65. package/framework/skills/why/references/source-playbook.md +17 -0
  66. package/framework/skills/why/references/sources/code-archaeology.md +88 -0
  67. package/framework/skills/why/references/sources/databricks.md +70 -0
  68. package/framework/skills/why/references/sources/datadog.md +99 -0
  69. package/framework/skills/why/references/sources/incident-postmortem.md +15 -0
  70. package/framework/skills/why/references/sources/linear.md +48 -0
  71. package/framework/skills/why/references/sources/notion.md +55 -0
  72. package/framework/skills/why/references/sources/sentry.md +100 -0
  73. package/framework/skills/why/references/sources/slack.md +54 -0
  74. package/framework/skills/why/references/synthesizer-prompt.md +135 -0
  75. package/package.json +1 -1
  76. package/src/catalog.js +13 -12
  77. package/framework/mcps/notion-mcp/README.md +0 -57
  78. package/framework/mcps/notion-mcp/capabilities.md +0 -118
  79. package/framework/mcps/notion-mcp/configs/opencode.json +0 -9
  80. package/framework/mcps/notion-mcp/install.md +0 -70
  81. package/framework/mcps/notion-mcp/troubleshooting.md +0 -95
  82. package/framework/skills/brainstorming/SKILL.md +0 -159
  83. package/framework/skills/brainstorming/examples.md +0 -49
  84. package/framework/skills/brainstorming/scripts/frame-template.html +0 -213
  85. package/framework/skills/brainstorming/scripts/helper.js +0 -167
  86. package/framework/skills/brainstorming/scripts/server.cjs +0 -723
  87. package/framework/skills/brainstorming/scripts/start-server.sh +0 -209
  88. package/framework/skills/brainstorming/scripts/stop-server.sh +0 -120
  89. package/framework/skills/brainstorming/visual-companion.md +0 -291
  90. package/framework/skills/code-review/SKILL.md +0 -72
  91. package/framework/skills/code-review/examples.md +0 -31
  92. package/framework/skills/codenavi/SKILL.md +0 -306
  93. package/framework/skills/codenavi/examples.md +0 -33
  94. package/framework/skills/codenavi/references/coding-principles.md +0 -143
  95. package/framework/skills/codenavi/references/notebook-spec.md +0 -171
  96. package/framework/skills/create-adr/SKILL.md +0 -429
  97. package/framework/skills/create-adr/examples.md +0 -35
  98. package/framework/skills/design/SKILL.md +0 -399
  99. package/framework/skills/design/examples.md +0 -34
  100. package/framework/skills/great-interface/SKILL.md +0 -43
  101. package/framework/skills/great-interface/references/animations.md +0 -205
  102. package/framework/skills/great-interface/references/better-accessibility.md +0 -106
  103. package/framework/skills/great-interface/references/better-colors.md +0 -100
  104. package/framework/skills/great-interface/references/better-interface.md +0 -132
  105. package/framework/skills/great-interface/references/better-layout.md +0 -76
  106. package/framework/skills/great-interface/references/better-typography.md +0 -157
  107. package/framework/skills/great-interface/references/better-ui.md +0 -107
  108. package/framework/skills/great-interface/references/better-writing.md +0 -109
  109. package/framework/skills/great-interface/references/choosing-fonts.md +0 -64
  110. package/framework/skills/great-interface/references/color-formats.md +0 -90
  111. package/framework/skills/great-interface/references/color-usage.md +0 -118
  112. package/framework/skills/great-interface/references/contrast.md +0 -79
  113. package/framework/skills/great-interface/references/css-cheat-sheet.md +0 -65
  114. package/framework/skills/great-interface/references/details-and-accessibility.md +0 -119
  115. package/framework/skills/great-interface/references/enter-exit.md +0 -147
  116. package/framework/skills/great-interface/references/explain-interface.md +0 -126
  117. package/framework/skills/great-interface/references/find-the-effect.md +0 -94
  118. package/framework/skills/great-interface/references/focus-and-keyboard.md +0 -131
  119. package/framework/skills/great-interface/references/forms.md +0 -84
  120. package/framework/skills/great-interface/references/from-an-image.md +0 -55
  121. package/framework/skills/great-interface/references/grouping-and-alignment.md +0 -123
  122. package/framework/skills/great-interface/references/hit-areas.md +0 -94
  123. package/framework/skills/great-interface/references/icon-transitions.md +0 -102
  124. package/framework/skills/great-interface/references/icons.md +0 -110
  125. package/framework/skills/great-interface/references/interface-review.md +0 -148
  126. package/framework/skills/great-interface/references/motion-and-zoom.md +0 -79
  127. package/framework/skills/great-interface/references/no-browser.md +0 -73
  128. package/framework/skills/great-interface/references/palette-generation.md +0 -104
  129. package/framework/skills/great-interface/references/palette-structure.md +0 -76
  130. package/framework/skills/great-interface/references/performance.md +0 -88
  131. package/framework/skills/great-interface/references/picker.md +0 -76
  132. package/framework/skills/great-interface/references/read-the-system.md +0 -178
  133. package/framework/skills/great-interface/references/removed-signals.md +0 -38
  134. package/framework/skills/great-interface/references/review-format.md +0 -46
  135. package/framework/skills/great-interface/references/scope-resolution.md +0 -88
  136. package/framework/skills/great-interface/references/screen-readers.md +0 -101
  137. package/framework/skills/great-interface/references/semantics-and-aria.md +0 -84
  138. package/framework/skills/great-interface/references/spacing-and-adaptivity.md +0 -159
  139. package/framework/skills/great-interface/references/spacing-and-sizing.md +0 -121
  140. package/framework/skills/great-interface/references/surfaces.md +0 -219
  141. package/framework/skills/great-interface/references/token-naming.md +0 -97
  142. package/framework/skills/great-interface/references/variable-fonts-and-opentype.md +0 -105
  143. package/framework/skills/great-interface/references/variant.md +0 -104
  144. package/framework/skills/great-interface/references/wrapping-and-punctuation.md +0 -55
  145. package/framework/skills/learning-opportunities/SKILL.md +0 -140
  146. package/framework/skills/learning-opportunities/examples.md +0 -34
  147. package/framework/skills/learning-opportunities/references/PRINCIPLES.md +0 -42
  148. package/framework/skills/notion-mcp/SKILL.md +0 -57
  149. package/framework/skills/notion-mcp/examples.md +0 -31
  150. package/framework/skills/notion-mcp/references/comments.md +0 -112
  151. package/framework/skills/notion-mcp/references/databases.md +0 -193
  152. package/framework/skills/notion-mcp/references/pages.md +0 -235
  153. package/framework/skills/spec-driven-eval/SKILL.md +0 -341
  154. package/framework/skills/spec-driven-eval/examples.md +0 -35
  155. package/framework/skills/spec-driven-eval/references/quickstart.md +0 -118
  156. package/framework/skills/spec-driven-eval/references/reference.md +0 -295
  157. package/framework/skills/technical-design-doc-creator/README.md +0 -411
  158. package/framework/skills/technical-design-doc-creator/SKILL.md +0 -1484
  159. package/framework/skills/technical-design-doc-creator/examples.md +0 -35
  160. package/framework/skills/web-design-guidelines/SKILL.md +0 -65
  161. package/framework/skills/web-design-guidelines/examples.md +0 -32
  162. package/framework/skills/web-design-guidelines/references/guideline.md +0 -174
@@ -1,84 +0,0 @@
1
- # Forms
2
-
3
- Labels, autocomplete, error messaging, input types and submit behavior.
4
-
5
- ## Labels
6
-
7
- Every control needs a programmatic label: `<label for>` pointing at the input's `id`, or a wrapping `<label>`. A placeholder is never a label. It disappears the moment the user types and usually fails contrast.
8
-
9
- ```html
10
- <!-- Good: explicit association -->
11
- <label for="email">Email</label>
12
- <input id="email" type="email" autocomplete="email" />
13
-
14
- <!-- Good: wrapping label, so label and control share one hit target -->
15
- <label>
16
- <input type="checkbox" /> Send me updates
17
- </label>
18
- ```
19
-
20
- Label and control share one hit target, so clicking "Send me updates" toggles the checkbox with no dead zone between them. Mark required fields with native `required` plus a visible indicator explained once per form ("* required").
21
-
22
- A placeholder used *in addition to* a label shows an example of the expected format: `placeholder="name@company.com"`.
23
-
24
- ## Error messaging
25
-
26
- The complete pattern:
27
-
28
- ```html
29
- <label for="email">Email</label>
30
- <input
31
- id="email"
32
- type="email"
33
- autocomplete="email"
34
- aria-invalid="true"
35
- aria-describedby="email-error"
36
- />
37
- <p id="email-error">Enter a valid email address.</p>
38
- ```
39
-
40
- - `aria-invalid="true"` on the failing field, removed once fixed.
41
- - `aria-describedby` links the field to its inline error so screen readers announce it with the field.
42
- - Errors render inline beside their fields, with an icon or text. Never a red border alone, which is a color-only cue.
43
- - On submit, focus the first invalid field.
44
- - Allow incomplete submission so validation can surface. Never disable submit until valid (see below).
45
- - Accept free text and validate after. Never block typing or filter characters as the user types. Trim values before validating, because autocomplete and text expansion add trailing spaces.
46
-
47
- ## Autocomplete and input types
48
-
49
- `autocomplete` with a meaningful `name` fills forms in one tap and is a WCAG requirement (1.3.5) for fields about the user. The common tokens:
50
-
51
- | Field | `autocomplete` |
52
- | --- | --- |
53
- | Name | `name` (or `given-name` / `family-name`) |
54
- | Email | `email` |
55
- | Phone | `tel` |
56
- | Address | `street-address`, `address-line1`, `postal-code`, `country` |
57
- | Card | `cc-number`, `cc-exp`, `cc-csc`, `cc-name` |
58
- | Login | `username`, `current-password` |
59
- | Signup / reset | `new-password` |
60
- | 2FA code | `one-time-code` |
61
-
62
- Prefix with a section where relevant: `autocomplete="shipping street-address"`.
63
-
64
- Correct `type` and `inputmode` pick the right mobile keyboard:
65
-
66
- | Input | Use |
67
- | --- | --- |
68
- | Email, URL, phone | `type="email"`, `type="url"`, `type="tel"` |
69
- | OTP / PIN / card number | `type="text" inputmode="numeric"` (keeps text semantics, no spinner) |
70
- | Money, decimals | `type="text" inputmode="decimal"` |
71
- | True numeric quantity | `type="number"` |
72
-
73
- Disable spellcheck on emails, codes and usernames: `spellcheck="false"`.
74
-
75
- ## Never fight the user's tools
76
-
77
- - Stay compatible with password managers and 2FA autofill: real `<form>`, correct `autocomplete`, no fake inputs.
78
-
79
- ## Submit behavior
80
-
81
- - Keep submit enabled until the request starts, then disable it and show a spinner *beside the original label*. "Save" with a spinner, not a bare spinner. The label is what tells assistive tech which button is busy.
82
- - Announce results. Success goes through a polite live region. On failure, focus the first invalid field, which is itself the announcement. Reserve `role="alert"` for form-level errors not tied to a field ([screen-readers.md](screen-readers.md)).
83
- - Warn on unsaved changes before navigation, and never lose typed input to a re-render. Hydration must preserve focus and value.
84
- - Enter submits from any focused input; in `<textarea>`, ⌘/Ctrl+Enter submits.
@@ -1,55 +0,0 @@
1
- # Reading a screenshot
2
-
3
- The method for a screenshot, where the answer is a reconstruction rather than a reading. Which property lands in which bucket:
4
-
5
- | Exact from pixels | Ratios only | Unavailable |
6
- | --- | --- | --- |
7
- | Color values | Type sizes | Tokens and their names |
8
- | Contrast between any two sampled colors | Spacing values | The stack and styling system |
9
- | Relative proportion of anything measurable | Radii | Breakpoints |
10
- | Which colors repeat and where | Stroke and border weights | Motion, easing, duration |
11
- | | | Every state but the captured one |
12
-
13
- You do not know the capture's scale. A screenshot may be at 1×, 2×, or browser zoom, so a measured 30px could be 15pt of type or 30. Never report a `px` size or spacing from an image alone.
14
-
15
- One exception. Where the image contains text you can identify as body copy, assume `16px` and express everything as a multiple of it. Say you did, since the assumption may be wrong.
16
-
17
- ## Colors, which are the reliable part
18
-
19
- Sample the actual pixels rather than describing what you see. Then hand the values to `better-colors`:
20
-
21
- - Convert each to OKLCH, so lightness is comparable across hues.
22
- - Sort by lightness to see whether the samples form a ramp and whether steps sit denser at the light end.
23
- - Check hue constancy across the ramp. A drifting hue means someone picked the ramp by eye.
24
- - Measure contrast on every foreground and background pair you can isolate. It is exact and the most valuable single number an image gives you.
25
- - Watch for a tinted neutral. A gray carrying a few percent of the accent hue is a deliberate choice worth naming.
26
-
27
- ## Type, by category not by name
28
-
29
- You cannot identify a typeface from a screenshot with confidence, so never claim one. You can read its category and features, which is what transfers:
30
-
31
- - **Category:** geometric sans, grotesque, humanist, transitional serif, slab. Say which and why.
32
- - **Tells worth naming:** single or double-storey `a` and `g`, terminal angle, aperture, x-height against cap height. Also whether the digits are lining or old-style and whether the figures look tabular.
33
- - **Scale:** count the distinct sizes. Express them as multiples of the body size and derive the ratio.
34
- - **Weight contrast:** how many weights and how far apart. Two weights three steps apart reads deliberate, four weights one step apart accidental.
35
- - **Measure:** count characters on a full line of body copy and compare against `better-typography`'s 60 to 75 range.
36
-
37
- Where the actual face matters, name the category and suggest identifying it from the live page.
38
-
39
- ## Spacing, as a rhythm
40
-
41
- Measure in the image, then divide everything by the smallest repeated gap. That quotient set is the rhythm, and it survives not knowing the scale.
42
-
43
- Then check the ratio `better-layout` owns, the gap between groups against the gap within one. At or above 2, space is carrying the grouping. Below that, something else is, usually a border or a background shape.
44
-
45
- ## Say what the image hid
46
-
47
- Close by naming what a screenshot could not show, since that is where the reader would otherwise assume you looked:
48
-
49
- - Hover, focus, active, disabled, loading, empty and error states.
50
- - Whether anything animates and how.
51
- - Behavior at any other width.
52
- - Whether it is keyboard reachable and whether focus is visible.
53
- - The other appearance, light or dark.
54
-
55
- Where any of these matter to the reader's question, say that a live URL would answer it and this image cannot.
@@ -1,123 +0,0 @@
1
- # Grouping and alignment
2
-
3
- How spacing, shapes, shared edges and ordering communicate what belongs together and what matters most.
4
-
5
- ## Group with space, not lines
6
-
7
- Three tools create grouping, in order of preference:
8
-
9
- 1. **Negative space**, the default. Related items sit close, unrelated ones far apart.
10
- 2. **Background shapes**, a card or filled container, where a group must read as one unit such as a selectable row or a draggable card.
11
- 3. **Separator lines**, a last resort for dense data where space costs too much, such as tables and long settings lists.
12
-
13
- The structural rule is that the gap between groups is at least 2× the gap within one. At `8px` inside a group, groups need `16px`+ between them, or the eye can't tell where one ends.
14
-
15
- ```css
16
- /* Good: spacing alone communicates the grouping */
17
- .field-group { display: flex; flex-direction: column; gap: 8px; }
18
- .form { display: flex; flex-direction: column; gap: 24px; }
19
-
20
- /* Bad: uniform spacing plus lines to compensate */
21
- .form > * { margin-bottom: 12px; border-bottom: 1px solid var(--separator); }
22
- ```
23
-
24
- ```html
25
- <!-- Good: Tailwind -->
26
- <div class="space-y-6">
27
- <div class="space-y-2">…field group…</div>
28
- <div class="space-y-2">…field group…</div>
29
- </div>
30
- ```
31
-
32
- Where a separator is genuinely needed, keep it quiet: hairline width, low contrast, never combined with a large gap that already did the job.
33
-
34
- ## Keep controls distinct from content
35
-
36
- Interactive elements need a visual signal: a background, a border, an underline, or placement in a consistent control zone such as a toolbar or footer row. A control styled identically to static text is invisible.
37
-
38
- ```html
39
- <!-- Bad: action looks exactly like the description text next to it -->
40
- <p class="text-zinc-600">Your trial ends soon. Upgrade now</p>
41
-
42
- <!-- Good: the action reads as an action -->
43
- <p class="text-zinc-600">Your trial ends soon.</p>
44
- <button class="font-medium text-blue-600">Upgrade now</button>
45
- ```
46
-
47
- The inverse holds too. A non-clickable badge shaped exactly like the buttons beside it collects dead clicks.
48
-
49
- ## Align to shared edges
50
-
51
- Pick a small set of alignment edges and put everything on them, because the eye tracks straight edges to scan content.
52
-
53
- - Every stray edge reads as noise even when nobody can name it: an icon 2px off the text edge, a card padded unlike its neighbor.
54
- - Use one project spacing step to express hierarchy. `16px` is a useful default where no scale exists, and deeper nesting repeats the same step.
55
- - Numbers in tables align to the trailing edge, text to the leading edge. Tabular figures are `better-typography`'s.
56
-
57
- ```css
58
- /* Good: one shared leading edge, one indent step */
59
- .section { padding-inline: 24px; }
60
- .section .child { margin-inline-start: 16px; }
61
-
62
- /* Bad: three unrelated leading edges in one column */
63
- .header { padding-inline-start: 20px; }
64
- .list-item { padding-inline-start: 14px; }
65
- .footer { padding-inline-start: 24px; }
66
- ```
67
-
68
- ## Logical properties, not physical
69
-
70
- Express direction-dependent horizontal position as leading/trailing so the layout mirrors automatically under `dir="rtl"`:
71
-
72
- | Physical (avoid) | Logical (use) |
73
- | --- | --- |
74
- | `margin-left` | `margin-inline-start` |
75
- | `padding-right` | `padding-inline-end` |
76
- | `left: 0` | `inset-inline-start: 0` |
77
- | `text-align: left` | `text-align: start` |
78
- | `border-right` | `border-inline-end` |
79
-
80
- ```html
81
- <!-- Good: Tailwind logical utilities -->
82
- <div class="ms-4 pe-6 text-start">…</div>
83
-
84
- <!-- Bad: breaks in RTL -->
85
- <div class="ml-4 pr-6 text-left">…</div>
86
- ```
87
-
88
- Reserve physical properties for things that refer to physical screen sides whatever the language, such as positioning against a device notch or matching a gesture direction.
89
-
90
- Where arrangement encodes progression, as in star ratings, step indicators and progress bars, the sequence mirrors in RTL and stars fill from the trailing side. Flexbox and grid with logical properties mirror automatically; hand-positioned elements do not. Digit order inside numbers never reverses, which with other bidi rules belongs to `better-typography`.
91
-
92
- ## Order by importance
93
-
94
- Readers scan top-to-bottom and leading-to-trailing. Place content accordingly:
95
-
96
- - The most important information sits near the top and the leading edge. The further down and trailing something sits, the less attention it gets.
97
- - Give essential information room. Never bury the one number the user came for under rows of secondary detail. Push that into collapsed sections, tabs, or detail views.
98
- - Within a row, identifying content leads and metadata and actions trail.
99
-
100
- ```html
101
- <!-- Good: primary fact first, detail demoted -->
102
- <div>
103
- <p class="text-2xl font-semibold">$4,320.00</p>
104
- <p class="text-sm text-zinc-500">Available balance</p>
105
- </div>
106
-
107
- <!-- Bad: the key fact is buried below the fold of the card -->
108
- <div>
109
- <p class="text-sm">Account 4402 · Opened 2019 · Standard tier</p>
110
- <p class="text-sm">Last statement: June 30</p>
111
- <p class="text-sm">Balance: $4,320.00</p>
112
- </div>
113
- ```
114
-
115
- With logical properties, the same hierarchy mirrors correctly in RTL locales.
116
-
117
- ## Don't overload the entry point
118
-
119
- The first screenful is a table of contents, not the whole book. If everything is prominent, nothing is:
120
-
121
- - One primary action per view. `better-colors` owns how color enforces it.
122
- - Group secondary actions behind a menu once they exceed two or three.
123
- - Prefer a short view that links deeper over a long view that shows everything at level one.
@@ -1,94 +0,0 @@
1
- # Hit areas
2
-
3
- Target sizes, expanding hit areas without changing visual size and collision rules.
4
-
5
- ## Target sizes
6
-
7
- Separate the conformance baseline from larger usability targets:
8
-
9
- | Standard | Minimum |
10
- | --- | --- |
11
- | WCAG 2.5.8 (AA) | 24×24px, the hard floor |
12
- | WCAG 2.5.5 (AAA) | 44×44px |
13
- | Apple HIG | 44×44pt |
14
- | Material Design | 48×48dp |
15
-
16
- WCAG 2.5.8 Level AA requires a 24×24 CSS-pixel target or one of its exceptions. Treat 44px as the recommended touch target for primary controls and 40px as a useful desktop target where density permits. Smaller controls are not automatic failures. Check the spacing, equivalent-control, inline, user-agent and essential exceptions before reporting one.
17
-
18
- Under the spacing exception, an undersized target passes when a 24px circle centered on its bounding box intersects no other target and no other undersized target's circle. In the simple case, 20px targets need a 4px gap.
19
-
20
- The visible element can stay small; the hit area is what must be big. Anything that looks clickable must be clickable across its whole visual extent, with no dead zones. A checkbox and its label share one hit target.
21
-
22
- ## Expanding the hit area
23
-
24
- Where the visible element is smaller, say a 20×20 checkbox, extend the hit area with a pseudo-element. Put it on the wrapping `<label>` or `<button>`, never on the `<input>`, because replaced elements don't render `::before`/`::after` reliably.
25
-
26
- ### CSS example
27
-
28
- ```css
29
- /* Small checkbox with expanded 44px hit area, on the wrapping label */
30
- .checkbox-label {
31
- position: relative;
32
- width: 20px;
33
- height: 20px;
34
- }
35
-
36
- .checkbox-label::after {
37
- content: "";
38
- position: absolute;
39
- top: 50%;
40
- left: 50%; /* physical centering: direction-independent */
41
- transform: translate(-50%, -50%);
42
- width: 44px;
43
- height: 44px;
44
- }
45
- ```
46
-
47
- ### Tailwind example
48
-
49
- ```tsx
50
- <button className="relative size-5 after:absolute after:top-1/2 after:left-1/2 after:size-11 after:-translate-1/2">
51
- <CheckIcon />
52
- </button>
53
- ```
54
-
55
- ### Layout alternative
56
-
57
- Where the element can afford real box size, skip the pseudo-element and let the box be the target. That hands the browser real geometry for scrolling and gestures:
58
-
59
- ```css
60
- .icon-button {
61
- min-width: 44px;
62
- min-height: 44px;
63
- display: inline-grid;
64
- place-items: center;
65
- }
66
- ```
67
-
68
- ## Collision rule
69
-
70
- Where the extended hit area overlaps another interactive element, shrink the pseudo-element to the largest size that does not collide. Two interactive elements never have overlapping hit areas.
71
-
72
- ## Decorative layers
73
-
74
- A decorative layer painted over interactive content absorbs every pointer event its box covers: a gradient scrim, a glow, a blurred sheen, a full-bleed `::after`. The control underneath looks live and does nothing, and no hit-area sizing fixes it.
75
-
76
- Give each one `pointer-events: none` (Tailwind `pointer-events-none`) so events reach the control below, plus `aria-hidden="true"` to keep it out of the accessibility tree:
77
-
78
- ```css
79
- .card-glow {
80
- position: absolute;
81
- inset: 0;
82
- pointer-events: none;
83
- }
84
- ```
85
-
86
- Keep pointer events on any layer the user is meant to hit: a modal scrim that dismisses on click is a control, not decoration.
87
-
88
- ## Touch behavior
89
-
90
- - Add `touch-action: manipulation` to interactive elements to remove the double-tap-to-zoom delay on mobile.
91
- - Set `touch-action: none` on a surface implementing its own pan, zoom, or drag gestures, so the browser stops claiming them for scrolling and pinch-zoom. Scope it to that surface; at page level it removes scrolling.
92
- - Set `-webkit-tap-highlight-color` to match the design instead of the default gray flash.
93
- - Put hover-only styling behind `@media (hover: hover)`. On touch, `:hover` latches after a tap and holds until the user taps elsewhere, so it reads as a stuck selected state. Tailwind 4's `hover:` variant already compiles under this query.
94
- - Prefer generous targets and clear affordances over finicky interactions such as tiny drag handles and precise hover zones.
@@ -1,102 +0,0 @@
1
- # Icon transitions
2
-
3
- Cross-fading an icon when it changes contextually or by state, with and without a motion library. Icon weight, color and direction live in [icons.md](icons.md).
4
-
5
- ## Contextual icon animations
6
-
7
- When icons appear or disappear contextually, on hover or a state change, animate them with `opacity`, `scale` and `blur` rather than toggling visibility.
8
-
9
- ### Motion example
10
-
11
- This uses the `motion` package. Where the project has `framer-motion`, import the same APIs from `"framer-motion"`. Never mix an installed package with the other's import path.
12
-
13
- ```tsx
14
- import { AnimatePresence, motion } from "motion/react";
15
-
16
- function IconButton({ isActive, icon: Icon }) {
17
- return (
18
- <button>
19
- <AnimatePresence mode="popLayout">
20
- <motion.span
21
- key={isActive ? "active" : "inactive"}
22
- initial={{ opacity: 0, scale: 0.25, filter: "blur(4px)" }}
23
- animate={{ opacity: 1, scale: 1, filter: "blur(0px)" }}
24
- exit={{ opacity: 0, scale: 0.25, filter: "blur(4px)" }}
25
- transition={{ type: "spring", duration: 0.3, bounce: 0 }}
26
- >
27
- <Icon />
28
- </motion.span>
29
- </AnimatePresence>
30
- </button>
31
- );
32
- }
33
- ```
34
-
35
- ### CSS transition approach (no Motion)
36
-
37
- Without Motion or Framer Motion, keep both icons in the DOM and cross-fade with CSS transitions. Neither unmounts, so enter and exit both animate smoothly.
38
-
39
- One icon is absolutely positioned on top of the other. Toggling state cross-fades them, the entering icon scaling up from `0.25` while the exiting one scales down to `0.25`, both with opacity and blur.
40
-
41
- ```tsx
42
- function IconButton({ isActive, ActiveIcon, InactiveIcon }) {
43
- return (
44
- <button>
45
- <div className="relative">
46
- <div
47
- className={cn(
48
- "absolute inset-0 flex items-center justify-center",
49
- "transition-[opacity,filter,scale] duration-300",
50
- "ease-[cubic-bezier(0.2,0,0,1)]",
51
- isActive
52
- ? "scale-100 opacity-100 blur-0"
53
- : "scale-[0.25] opacity-0 blur-[4px]"
54
- )}
55
- >
56
- <ActiveIcon />
57
- </div>
58
- <div
59
- className={cn(
60
- "transition-[opacity,filter,scale] duration-300",
61
- "ease-[cubic-bezier(0.2,0,0,1)]",
62
- isActive
63
- ? "scale-[0.25] opacity-0 blur-[4px]"
64
- : "scale-100 opacity-100 blur-0"
65
- )}
66
- >
67
- <InactiveIcon />
68
- </div>
69
- </div>
70
- </button>
71
- );
72
- }
73
- ```
74
-
75
- The non-absolute icon, `InactiveIcon`, defines the layout size. The absolute one, `ActiveIcon`, overlays it without affecting flow.
76
-
77
- ### Choosing between Motion and CSS
78
-
79
- | | Motion (Framer Motion) | CSS transitions (both icons in DOM) |
80
- | --- | --- | --- |
81
- | **Enter animation** | Yes | Yes |
82
- | **Exit animation** | Yes (via `AnimatePresence`) | Yes (cross-fade, icon never unmounts) |
83
- | **Spring physics** | Yes | No, use `cubic-bezier(0.2, 0, 0, 1)` as approximation |
84
- | **When to use** | Project already uses `motion` or `framer-motion` | No motion dependency, or keeping bundle small |
85
-
86
- Check the project's `package.json`. Import from `"motion/react"` when `motion` is installed, or `"framer-motion"` when that is. Where both exist, follow the imports the component or its nearest peers already use. Where neither is present, use the CSS cross-fade and never add a dependency just for icon transitions.
87
-
88
- ### When to animate icons
89
-
90
- | Animate | Don't animate |
91
- | --- | --- |
92
- | Icons that appear on hover (action buttons) | Static navigation icons |
93
- | State change icons (play → pause, like → liked) | Decorative icons |
94
- | Icons in contextual toolbars | Icons that are always visible |
95
- | Loading/success state indicators | Icon labels (text next to icon) |
96
-
97
- Use exactly these values for contextual icon animations. Do not deviate:
98
- - `scale`: `0.25` → `1` (never use `0.5` or `0.6`)
99
- - `opacity`: `0` → `1`
100
- - `filter`: `"blur(4px)"` → `"blur(0px)"`
101
- - `transition`: `{ type: "spring", duration: 0.3, bounce: 0 }`; **bounce must always be `0`**, never `0.1` or any other value
102
-
@@ -1,110 +0,0 @@
1
- # Icons
2
-
3
- Icon weight, states, sizing and direction, the details that make icons sit naturally in an interface.
4
-
5
- ## Match icon stroke to text weight
6
-
7
- A hairline icon beside semibold text reads as broken; a heavy icon beside regular text shouts.
8
-
9
- | Adjacent text | Icon stroke width (24px grid) |
10
- | --- | --- |
11
- | Regular (400), 14–16px | `1.5px` |
12
- | Medium/Semibold (500–600) | `2px` |
13
- | Bold (700), or emphasized standalone | `2.5px` |
14
-
15
- ```html
16
- <!-- Good: stroke tuned to the label weight -->
17
- <button class="flex items-center gap-2 font-semibold">
18
- <PlusIcon stroke-width="2" class="size-4" />
19
- New project
20
- </button>
21
-
22
- <!-- Bad: default 1.5px stroke against a bold label -->
23
- <button class="flex items-center gap-2 font-bold">
24
- <PlusIcon stroke-width="1.5" class="size-4" />
25
- New project
26
- </button>
27
- ```
28
-
29
- Two related consistency rules:
30
-
31
- - **One optical strategy per surface.** Never mix icon libraries with incompatible stroke conventions on one toolbar. Where the library supports stroke variants, match them to adjacent text as above; otherwise keep the set's native stroke and use size or color for emphasis.
32
- - **Size icons relative to the text's cap height**, typically `1em`–`1.25em` when inline with text, so the pair scales together.
33
-
34
- ## One SVG, recolored per state
35
-
36
- Never ship separate assets for default, hover, selected and disabled states. Use one SVG drawn with `currentColor` and let CSS state drive the color:
37
-
38
- ```html
39
- <!-- Good: one asset, states are CSS -->
40
- <svg fill="none" stroke="currentColor" stroke-width="2">…</svg>
41
- ```
42
-
43
- ```css
44
- .icon-button { color: oklch(0.552 0.016 285.938); }
45
- .icon-button:hover { color: oklch(0.21 0.006 285.885); }
46
- .icon-button[aria-pressed="true"] { color: oklch(0.623 0.188 259.815); }
47
- .icon-button:disabled { opacity: 0.4; }
48
- ```
49
-
50
- ```html
51
- <!-- Tailwind -->
52
- <button class="text-zinc-500 hover:text-zinc-900 aria-pressed:text-blue-600 disabled:opacity-40">
53
- <BookmarkIcon />
54
- </button>
55
- ```
56
-
57
- Hardcoded fills inside the SVG, such as `fill="#666"`, break this. Strip them to `currentColor` when importing icons.
58
-
59
- ## Outline default, fill active
60
-
61
- Where an icon set offers outline and filled variants, use them as a state pair, never interchangeably:
62
-
63
- | Variant | Use for |
64
- | --- | --- |
65
- | Outline | Default state: toolbars, list rows, inline with text |
66
- | Fill | Selected/active state: the active tab, a toggled bookmark, a liked heart |
67
-
68
- ```tsx
69
- // Good: variant communicates state
70
- <TabIcon variant={isActive ? "solid" : "outline"} />
71
-
72
- // Bad: filled icons everywhere, so the active tab has no state signal
73
- <TabIcon variant="solid" />
74
- ```
75
-
76
- The swap between variants is a contextual icon animation. Use the exact cross-fade values in [icon-transitions.md](icon-transitions.md).
77
-
78
- ## Design at render size
79
-
80
- An icon that looks great at 48px collapses into mush at 16px. Thin interior lines, tight counters and fine texture all blur or alias when small.
81
-
82
- - Test every icon at the smallest size it will render, often `16px`. It must stay recognizable there.
83
- - Prefer simplified glyphs for small contexts over scaling down detailed artwork.
84
- - Keep icons on the pixel grid at their render size. A 16px icon drawn on a 24px grid with fractional scaling renders soft, so use the set's native grid sizes (`16`, `20`, `24`) rather than arbitrary scales.
85
- - Always SVG, never raster, so the same asset stays crisp at every density.
86
-
87
- ## Icons in RTL
88
-
89
- Under `dir="rtl"`, flip icons whose meaning is tied to reading direction, and leave the rest alone:
90
-
91
- | Flip | Don't flip |
92
- | --- | --- |
93
- | Back/forward arrows, chevrons in navigation | Logos and brand marks |
94
- | Text-block glyphs (alignment, lists, indent) | Checkmarks |
95
- | Speaker/volume waves (emanate in reading direction) | Physical objects: clocks, cups, pencils |
96
- | "Send" style directional glyphs | Media playback (play/rewind refer to tape direction, convention keeps them LTR) |
97
-
98
- ```css
99
- /* Good: mirror only direction-dependent icons */
100
- [dir="rtl"] .icon-directional {
101
- scale: -1 1;
102
- }
103
- ```
104
-
105
- ```html
106
- <!-- Tailwind -->
107
- <ChevronRightIcon class="icon-directional rtl:-scale-x-100" />
108
- ```
109
-
110
- Analyze composite icons part by part. A badge or slash overlay may keep its position even when the base glyph flips. Accessible names for icon-only buttons belong to `better-accessibility`.