@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,148 +0,0 @@
1
- # Change review
2
-
3
- This skill reviews a change rather than a screen. It resolves the scope, expands the changed files to the surfaces they affect, reads both sides of the diff and classifies every finding.
4
-
5
- Scope is all it owns. Domain rules belong to the `better-*` skills. Severity, consolidation, coverage, the cap and the verdict belong to `better-interface`, which this skill hands the review to.
6
-
7
- Correctness, tests, security and performance belong to the project's general code review. Name the concern once and move on.
8
-
9
- ## The change, not the codebase
10
-
11
- The author is asking "did I make this worse?". Report what the change caused and stay mostly quiet about what it merely touched. Three pre-existing findings is a courtesy; thirty is a different review and one nobody asked for.
12
-
13
- Read the change before forming an opinion of it. The stated intent decides what counts as incomplete, and a skimmed diff produces findings about code the next hunk already fixed.
14
-
15
- ## Core principles
16
-
17
- ### 1. Resolve the change scope first
18
-
19
- The whole invocation is the target, so `/interface-review pr 482` reviews pull request 482. [Scope resolution]() holds the accepted targets and how each resolves.
20
-
21
- With no target supplied, resolve in this order and stop at the first match:
22
-
23
- 1. `HEAD` is ahead of `git merge-base origin/<default-branch> HEAD`: that range **plus** any uncommitted changes, with the commit count and the uncommitted file count stated separately.
24
- 2. The working tree is dirty: the uncommitted changes.
25
- 3. Neither: there is no change to review. Stop and ask, per **With no change, ask rather than invent one**.
26
-
27
- Order matters. Check the working tree first and one stray formatting edit shadows a twelve-commit branch, with the report still claiming full coverage.
28
-
29
- Exclude lockfiles, snapshots, generated output, vendored code and binaries, and name what you excluded. An empty scope after exclusions reaches the same place by a different route.
30
-
31
- ### 2. With no change, ask rather than invent one
32
-
33
- A clean tree with nothing ahead of the merge base means the user asked to review a change that does not exist. Never fall back to `HEAD~1..HEAD` on your own. The last commit is whatever happened to land, often a merge, often someone else's work, and a report on it is indistinguishable from a report on what the user meant.
34
-
35
- State the repository facts you found, then offer the routes and wait. [Nothing to review]() holds the facts to gather:
36
-
37
- - **The last commit**, `HEAD~1..HEAD`, named by short SHA and subject, so the user sees what they would get before choosing it.
38
- - **A target they name**: `pr <n>`, a branch, a ref, or a range, resolved per **Resolve the change scope first**.
39
- - **A whole-repository interface audit**, which is not a change review. Hand it to `better-interface` as a repository-scope review, without this skill's scope block, statuses, or pre-existing section. With no change, every finding is pre-existing and the classification says nothing.
40
-
41
- Check for an open pull request on the current branch before asking, and offer it first. A branch whose commits already landed resolves to no change, while its pull request is still exactly what the user meant.
42
-
43
- Where the scope emptied out after exclusions, say which files were excluded and ask the same way. Never report a review of nothing as `Approve`.
44
-
45
- ### 3. A diff is not a surface
46
-
47
- A changed file is evidence, not the review subject. Its **blast radius** is the set of surfaces it renders in; review those.
48
-
49
- Expand the blast radius one hop by default: the direct importers and callers. Expand a second hop only for design tokens, theme values and shared primitives, where one line reaches the whole product.
50
-
51
- Review at most five consumers, ordered by [the rule in Scope resolution](), then state how many you did not expand. A sweep with no bound cannot support the coverage it claims, and an unstated cutoff reads as completeness.
52
-
53
- ### 4. Read the removed lines
54
-
55
- Regressions are invisible in the post-change state. Read the `-` side of every hunk against [Removed signals]().
56
-
57
- A signal is a lead, not a finding. A removal is only a regression when nothing in the change replaces it, and the domain skill owns that judgement. Route each unmatched removal to its owner, report only what that skill confirms and status it `Regression`. That tells the author they broke something that worked rather than made a new mistake.
58
-
59
- ### 5. Classify every finding
60
-
61
- Give every finding one status:
62
-
63
- - `Introduced`: the change created it.
64
- - `Regression`: the change weakened something previously correct.
65
- - `Pre-existing`: present in the touched code but not caused by this change.
66
-
67
- Status by what the diff touched, not by which file it sits in: a line the change never touched is `Pre-existing` even three lines from a hunk. Confirm against the base ref when it matters:
68
-
69
- ```bash
70
- git blame -L <line>,<line> "$BASE" -- path/to/file
71
- ```
72
-
73
- Hand every finding up with its status attached and let `better-interface` apply its cap and verdict rules.
74
-
75
- ### 6. Hold the change to its stated intent
76
-
77
- Read the pull request title and body, the linked issue and the commit messages, then review whether the interface delivers what they claim.
78
-
79
- This is what surfaces the **incomplete** change. A surface review cannot see it, because it inspects the states that are present, and here the point is the ones that are absent:
80
-
81
- - A new variant, size, or theme applied to some states but not all: hover, focus, active, disabled, loading, selected.
82
- - A new user-facing string with no entry in the translation catalogue the project maintains.
83
- - A new component with no empty, loading, error, disabled, or narrow-width state.
84
- - A control added to one surface but not to the siblings that already carry its peers.
85
-
86
- Do not report scope creep. Whether a change does too much is a process question, not an interface one.
87
-
88
- ### 7. Hand the review to `better-interface`
89
-
90
- Hand `better-interface` the scope block, the affected surfaces and a status on every finding. It routes to the domain skills, applies severity, consolidates, enforces the cap and issues the verdict.
91
-
92
- If `better-interface` is unavailable, report the resolved scope and the file inventory, name it as the missing skill and stop. Do not invent a severity scale, a cap, or a verdict.
93
-
94
- ### 8. Never mutate the working tree
95
-
96
- A change review is read-only, including the checkout. Fetch pull request refs; never check them out. `git fetch` writes only to `.git` and is permitted. `gh pr checkout`, `git checkout`, `git switch` and `git stash` rewrite the files the author has open. They fail against local edits or discard them, so they are never permitted.
97
-
98
- Rendered verification is opt-in. Mark visual and runtime claims **Not verified** unless the project exposes a cheap preview or the user asks for a rendered review. When they do, use an isolated worktree (`git worktree add /tmp/review-<n> refs/remotes/pr/<n>`) and remove it when done.
99
-
100
- ## Before you finish
101
-
102
- | Mistake | Fix |
103
- | --- | --- |
104
- | One stray edit reviewed instead of the branch | Check `merge-base` before the working tree, and report both counts |
105
- | The last commit reviewed because there was no change | State the facts and offer the last commit, a named target, or a repository audit |
106
- | Hunks reviewed without their consumers | Expand one hop, two for tokens and primitives, and name what you skipped |
107
- | Only the `+` side of the diff read | Search the `-` side for removed accessibility, focus, motion and text signals |
108
- | An equivalent replacement reported as a regression | Route the removal to its owner; report only what it confirms |
109
- | A removal reported as a new mistake | Status it `Regression` so the author knows it used to work |
110
- | A line near a hunk statused `Introduced` | Status by what the diff touched, confirmed with `git blame` against the base ref |
111
- | A pull request checked out to review it | Fetch the ref and review it in place |
112
- | Line numbers cited that do not exist on the reviewed ref | Cite against the head ref named in the scope block |
113
- | The severity scale or the finding cap restated here | Defer to `better-interface` |
114
- | Correctness, test, or security findings in the report | Name the concern once, point at the project's code review and drop it |
115
-
116
- ## Review output format
117
-
118
- Open with the scope block:
119
-
120
- | Field | Value |
121
- | --- | --- |
122
- | Target | `branch`, `working`, `staged`, `pr 482`, or the range as entered |
123
- | Base ref | `origin/main` at `a1b2c3d` |
124
- | Head ref | `refs/remotes/pr/482` at `e4f5g6h` |
125
- | Commits | 7 committed, 2 files uncommitted |
126
- | Files in scope | 12 after exclusions |
127
- | Excluded | `pnpm-lock.yaml`, `src/__snapshots__/`: lockfile and snapshots |
128
- | Surfaces expanded | `CheckoutPage`, `SettingsPanel`; 3 further `Button` consumers not expanded |
129
-
130
- The coverage table follows it unchanged. A domain with no evidence in the change scope is `Not reviewed: no evidence in the change scope`, which is a coverage statement rather than a gap.
131
-
132
- Then the findings, with a `Status` column per **Classify every finding**:
133
-
134
- | Severity | Domain | Status | Location | Before | After | Why |
135
- | --- | --- | --- | --- | --- | --- | --- |
136
- | HIGH | Accessibility | Regression | `src/Dialog.tsx:42` | `aria-label="Close"` removed in this change | Restore `aria-label="Close"` on the icon-only control | The close control had an accessible name before this change and no longer does |
137
-
138
- With no `Introduced` or `Regression` findings, omit the table and state "No actionable interface findings in this change."
139
-
140
- Then `Pre-existing` findings, at most three, highest severity first, stated plainly as not this change's responsibility. Omit the section when there are none.
141
-
142
- | Severity | Domain | Location | Issue |
143
- | --- | --- | --- | --- |
144
- | MEDIUM | Typography | `src/Toolbar.tsx:7` | Numeric badges use proportional figures; predates this change |
145
-
146
- The cap and the verdict cover `Introduced` and `Regression` only. `Pre-existing` findings sit outside the cap, so touching a legacy file cannot turn into a full-file audit. They sit outside the verdict too, so a change whose only findings are pre-existing is an `Approve`.
147
-
148
- End with `Block` when any `HIGH` remains and `Approve` otherwise, leaving the remaining findings in the table as work to do. When `better-interface` is available, the severity scale and the cap come from it.
@@ -1,79 +0,0 @@
1
- # Motion and zoom
2
-
3
- `prefers-reduced-motion`, zoom and reflow, and unit choices that respect user settings.
4
-
5
- ## prefers-reduced-motion
6
-
7
- Make motion opt-in. Wrap animations in `@media (prefers-reduced-motion: no-preference)` so users who asked for reduced motion get the static version by default, rather than you chasing every animation with an override.
8
-
9
- ```css
10
- /* Good: motion is opt-in */
11
- .card {
12
- /* static styles */
13
- }
14
- @media (prefers-reduced-motion: no-preference) {
15
- .card {
16
- transition: transform 200ms ease-out;
17
- }
18
- }
19
- ```
20
-
21
- ```tsx
22
- // Tailwind: motion-safe / motion-reduce variants
23
- <div className="motion-safe:transition-transform motion-safe:hover:-translate-y-1" />
24
- ```
25
-
26
- For an existing codebase where opt-in isn't feasible, the global kill switch is the fallback:
27
-
28
- ```css
29
- @media (prefers-reduced-motion: reduce) {
30
- *, *::before, *::after {
31
- animation-duration: 0.01ms !important;
32
- animation-iteration-count: 1 !important;
33
- transition-duration: 0.01ms !important;
34
- scroll-behavior: auto !important;
35
- }
36
- }
37
- ```
38
-
39
- `0.01ms` rather than `none`, so `animationend` and `transitionend` still fire and JS waiting on them doesn't hang.
40
-
41
- ### What to disable vs reduce
42
-
43
- Reduced motion means reduced, not eliminated. It targets vestibular triggers, not feedback.
44
-
45
- | Disable entirely | Replace | Keep |
46
- | --- | --- | --- |
47
- | Parallax scrolling | Slide/scale/zoom transitions → opacity crossfade | Loading spinners and progress |
48
- | Autoplaying video, GIFs, looping decoration | Smooth scrolling → instant jump | Instant state changes (hover color, focus ring) |
49
- | Spinning, large-scale movement across the screen | Auto-rotating carousels → start paused | Brief functional feedback (button press) |
50
-
51
- Animations are interruptible and driven by user input. Nothing autoplays or refuses to stop, and under reduced motion carousels start paused.
52
-
53
- ## Autoplay and timed UI
54
-
55
- Motion the user didn't ask for and UI acting on its own schedule:
56
-
57
- - **No autoplaying media without visible controls** (WCAG 2.2.2). Anything moving, blinking, or updating on its own for more than 5 seconds needs a visible pause or stop control, muted looping hero videos included.
58
- - **Prefer explicit dismissal over timers.** Auto-dismissal suits low-stakes confirmations and nothing else. A toast carrying an action, an error, or information the user may need stays until dismissed. Where one must time out, 5 seconds is the floor, and hovering or focusing it pauses the timer.
59
- - **Never put critical information only in a timed element.** A vanished toast with the only link to an undo action is data loss on a schedule.
60
-
61
- ## Zoom and reflow
62
-
63
- - **200% zoom** (WCAG 1.4.4). All content and functionality survives text scaled to 200%, and the viewport leaves the reader able to zoom.
64
- - **Reflow at 320px** (WCAG 1.4.10). At 400% zoom on a 1280px viewport, equivalent to a 320px one, the page must work with vertical scrolling alone. Genuinely 2D content is the exception: tables, maps and code blocks scroll inside their own container.
65
-
66
- Fixed heights are what break under zoom. Use `min-height` on anything containing text and let containers grow.
67
-
68
- ### rem vs px
69
-
70
- Respect how the codebase is set up. Where the project sizes in `px`, or on an established Tailwind scale, stay consistent and never introduce mixed units into someone else's system. Where you do have the choice, in new code or a codebase already on `rem`, `rem` respects the user's base font size and `px` ignores it:
71
-
72
- | Use `rem` | Use `px` |
73
- | --- | --- |
74
- | `font-size` | Borders and hairlines |
75
- | `max-width` of text containers | Focus outline width and offset |
76
- | Media-query breakpoints (`@media (min-width: 48rem)`) | `box-shadow` details |
77
- | Spacing that should scale with text | Fixed-size decorations |
78
-
79
- Breakpoints are where the choice matters most. At a larger base font size an `em` or `rem` query switches to the mobile layout when the text needs it, and a `px` query does not.
@@ -1,73 +0,0 @@
1
- # Reading a site without a browser
2
-
3
- Fetch the HTML, then the stylesheets it links, then grep. That answers most questions a scriptable browser answers and a few it cannot.
4
-
5
- Do not use a markdown-converting fetch for this. It strips exactly what you came for. Fetch the raw bytes.
6
-
7
- ```bash
8
- curl -sL --max-time 25 "$URL" -o page.html
9
- wc -c page.html
10
- grep -oE 'href="[^"]*\.css[^"]*"' page.html | sed 's/href="//;s/"$//' | sort -u
11
- ```
12
-
13
- Pull each stylesheet the same way, resolving protocol-relative and root-relative hrefs against the page's origin first.
14
-
15
- ## Utility CSS is self-describing
16
-
17
- Where the site uses utility classes, the markup already contains the declarations and no stylesheet lookup is needed. Grep the class attribute for the effect:
18
-
19
- ```bash
20
- grep -oE '(backdrop-)?blur-\[[^]]*\]|(backdrop-)?blur-[a-z0-9]+' page.html | sort | uniq -c | sort -rn
21
- grep -oE 'class="[^"]*(gradient|blur|mask|mix-blend)[^"]*"' page.html | head -20
22
- ```
23
-
24
- This is where the fetch method beats a browser. A class list carries every responsive and state variant at once, so `blur-[50px] md:h-214 md:-translate-x-1/2` says the element changes shape at the `md` breakpoint. Computed styles read at one width cannot.
25
-
26
- Semantic CSS gives you a hashed class name instead (`Hero_glow__a1b2c`). Take that name to the stylesheet and grep it there.
27
-
28
- ## Inline styles carry the values utilities cannot express
29
-
30
- A multi-stop gradient is usually too specific for a utility, so it lands in a `style` attribute:
31
-
32
- ```bash
33
- grep -oE 'linear-gradient\([^)]*\)' page.html | sort -u | head
34
- grep -oE 'radial-gradient\([^)]*\)' page.html | sort -u | head
35
- grep -oE 'style="[^"]*(transform|filter|mask)[^"]*"' page.html | head
36
- ```
37
-
38
- ## The stylesheet, for tokens and generated utilities
39
-
40
- ```bash
41
- grep -oE ':root\{[^}]*\}' style.css | head -1 | tr ';' '\n' # the token layer
42
- grep -oE '@layer [a-z]+' style.css | sort -u # Tailwind v4 emits theme/base/components/utilities
43
- grep -oE '@media[^{]*\(m(in|ax)-width:[^)]*\)' style.css | sort -u # real breakpoints
44
- grep -oE '@font-face\{[^}]*\}' style.css | head # families, weights, formats
45
- grep -oE '@keyframes [a-zA-Z-]+' style.css | sort -u # named animations
46
- ```
47
-
48
- To understand a custom utility, grep its class name in the stylesheet and read the declaration whole. That is how `gradient-ease-in-out` turns into its mechanism, a generated stop list built with `color-mix()` and relative color syntax rather than twelve hand-written stops.
49
-
50
- ## Stack fingerprints from the HTML alone
51
-
52
- ```bash
53
- grep -ocE '__NEXT_DATA__|/_next/static' page.html # Next.js
54
- grep -oc 'self.__next_f' page.html # App Router with RSC payload
55
- grep -ocE '__NUXT__|/_nuxt/' page.html # Nuxt
56
- grep -ocE '__remixContext|___gatsby|astro-island' page.html # Remix, Gatsby, Astro
57
- grep -oc 'class="[^"]*svelte-' page.html # Svelte
58
- grep -oc 'data-radix-' page.html # Radix primitives
59
- grep -oc 'bg-linear-to' page.html # Tailwind v4 (v3 wrote bg-gradient-to)
60
- grep -oE '<meta name="generator"[^>]*>' page.html
61
- ```
62
-
63
- Report these as fingerprints with the evidence that produced them, never as facts. `/_next/static` in an asset path is strong; a utility-looking class name alone is weak.
64
-
65
- ## What this method cannot tell you
66
-
67
- Say so rather than guessing past it:
68
-
69
- - **Which rule won.** Nine rules may match one element; only a browser resolves the cascade.
70
- - **Anything injected at runtime.** CSS-in-JS, a theme applied by script, styles added on interaction.
71
- - **Paint order and what is actually visible.** A declaration in the CSS may be overridden or never rendered.
72
- - **Live animation state.** Whether an effect moves at all.
73
- - **Computed values.** A `rem` stays a `rem`, and you never learn the resolved pixel size.
@@ -1,104 +0,0 @@
1
- # Palette generation
2
-
3
- Producing the values once the structure is decided. For which ramps to build and what each step is for, see [palette-structure.md](palette-structure.md).
4
-
5
- ## Start from the brand color
6
-
7
- A brand color arrives as one value, usually a hex. Two decisions come before any ramp exists:
8
-
9
- **Which step does it occupy?** A brand color meant for buttons and links belongs on the solid-fill step: `500` in Tailwind, `9` in Radix. Then `bg-brand-500` renders the actual brand color, not an approximation.
10
-
11
- **Is it pinned or snapped?** Pin a contractually fixed brand color. It stays exact, the ramp builds outward from it and that one step spaces slightly unevenly. Otherwise snap it onto the ramp so every step spaces evenly. That looks better almost always, and nobody notices without a swatch held to the screen.
12
-
13
- A brand color that fails contrast behind white text is still the brand color, just not the solid-fill step. Put it where it lands and use a darker step for interactive fills. Never quietly darken the brand.
14
-
15
- ## What a correct ramp looks like
16
-
17
- Properties of the finished ramp, checkable against any output in any notation:
18
-
19
- - **Steps are evenly spaced in perceived lightness.** Not in the number your format calls "lightness". HSL's is not perceptual, and evenly spaced HSL values bunch at one end.
20
- - **Hue is constant end to end.** Every step is recognisably the same color. A wandering hue reads as two colors blended and will not sit correctly against a neutral built on a different hue.
21
- - **Vividness peaks in the middle and falls off at both ends.** The lightest and darkest steps are nearly neutral; the middle carries the color. Holding full vividness into the extremes gives a `50` that glows and a `950` like ink spilled on the brand.
22
- - **Steps are denser at the light end.** Light backgrounds need finer distinctions than dark ones. Keep `50` to `200` close together and `800` to `950` further apart. Even spacing across the whole range makes the pale end unusable, because `50` and `100` stop reading as two surfaces.
23
- - **No two adjacent steps are indistinguishable.** If `200` and `300` look identical on a calibrated screen, the ramp has more steps than decisions. Drop one.
24
- - **Both ends stop short of pure black and white.** A ramp that reaches them loses its identity exactly where the page background lives.
25
-
26
- ## Use a color library
27
-
28
- Never compute these by hand or by eye. `culori`, `colorjs.io` and `chroma.js` all convert between notations, measure perceived lightness and interpolate perceptually. Read the brand color in whatever format it arrives, do the math in a perceptual space and emit the project's notation:
29
-
30
- ```js
31
- import { formatHex, interpolate, samples } from 'culori'
32
-
33
- // Perceptual interpolation, hex in and hex out.
34
- const ramp = interpolate(['#eff6ff', '#3b82f6', '#172554'], 'lab')
35
- const steps = samples(11).map((t) => formatHex(ramp(t)))
36
- ```
37
-
38
- The output format is the project's choice. For a ramp the interpolation space is not, because the steps have to land evenly in perceived lightness and sRGB interpolation produces muddy mid-steps. Decorative gradients are the opposite case, where the space is a deliberate look ([color-usage.md](color-usage.md)).
39
-
40
- ```css
41
- :root {
42
- --brand-50: #eff6ff;
43
- --brand-100: #dbeafe;
44
- --brand-200: #bfdbfe;
45
- --brand-300: #93c5fd;
46
- --brand-400: #60a5fa;
47
- --brand-500: #3b82f6;
48
- --brand-600: #2563eb;
49
- --brand-700: #1d4ed8;
50
- --brand-800: #1e40af;
51
- --brand-900: #1e3a8a;
52
- --brand-950: #172554;
53
- }
54
- ```
55
-
56
- ## Several hues at once
57
-
58
- With an accent plus status ramps, the ramps must agree step for step. `danger-500` and `brand-500` should read as equally bright and vivid, or a red button looks heavier than a blue one at the same step.
59
-
60
- - **Match perceived lightness exactly.** Same step, same brightness, across every hue.
61
- - **Match vividness relatively, not absolutely.** Hues do not share a maximum vividness. A saturated yellow and a saturated blue are not equally far from gray, and no format makes them so. Set each ramp to the same *proportion* of what its own hue reaches. Copying a saturation number across hues leaves one washed out.
62
-
63
- Yellows and cyans are the usual casualties, peaking much lower than reds and blues. Copy the numbers across and the warning color looks weak beside the danger one.
64
-
65
- ## Dark mode
66
-
67
- A dark palette is not the light one reversed. Reversal is the starting point, not the output.
68
-
69
- Swap the semantic roles first, then tune the values:
70
-
71
- ```css
72
- :root {
73
- --color-bg: var(--brand-50);
74
- --color-text: var(--brand-950);
75
- }
76
-
77
- .dark {
78
- --color-bg: var(--brand-950);
79
- --color-text: var(--brand-50);
80
- }
81
- ```
82
-
83
- Three things almost always need hand-tuning after the swap:
84
-
85
- - **Vividness comes down.** A color that reads as confident on white reads as neon on near-black. Dark appearances need the accent a step or two less vivid.
86
- - **The dark end needs more separation.** Steps distinguishable as pale backgrounds collapse into each other as dark surfaces.
87
- - **Contrast does not survive the mirror.** A pair passing in light mode can fail reversed, because contrast is not symmetric. Recheck every foreground against its real background in both appearances ([contrast.md](contrast.md)).
88
-
89
- ### Choosing the switching mechanism
90
-
91
- Pick one and use it throughout:
92
-
93
- - **`prefers-color-scheme` alone** is correct with no theme toggle. Nothing to persist, nothing to hydrate.
94
- - **A `.dark` class** is required as soon as users can override the system setting. The media query then sets only the initial value.
95
- - **`light-dark()`** collapses both values into one declaration, the least code when the project also sets `color-scheme`. It reads that property rather than a class, so a class-based toggle must set `color-scheme` too.
96
-
97
- ```css
98
- :root {
99
- color-scheme: light dark;
100
- --color-bg: light-dark(#ffffff, #172554);
101
- }
102
- ```
103
-
104
- Mixing mechanisms is the common failure. A media query setting some tokens and a class setting others gives a half-themed interface the moment a user overrides their system preference.
@@ -1,76 +0,0 @@
1
- # Palette structure
2
-
3
- What a color system is made of, before any values exist. For computing the values see [palette-generation.md](palette-generation.md); for what to call them see [token-naming.md](token-naming.md).
4
-
5
- ## What a system needs
6
-
7
- Most products need three kinds of ramp and nothing else:
8
-
9
- | Ramp | How many | Notes |
10
- | --- | --- | --- |
11
- | Neutral | 1 | Carries 80–90% of the interface: backgrounds, borders, body text |
12
- | Accent | 1 | The brand hue. Interactive and selected states |
13
- | Status | 0–4 | `danger`, `warning`, `success`, `info`. Add one only when the product shows that state |
14
-
15
- A second accent hue must also never sit adjacent to the first. Where it would, the accent ramp's own steps provide the range.
16
-
17
- ## Every step has a job
18
-
19
- Each step maps to a role. Generate the steps the roles below call for and skip the rest.
20
-
21
- | Role | Tailwind | Radix |
22
- | --- | --- | --- |
23
- | Page background | `50` | `1` |
24
- | Subtle background | `50` | `2` |
25
- | Component background | `100` | `3` |
26
- | Component hover | `200` | `4` |
27
- | Component active / selected | `200` | `5` |
28
- | Subtle border | `200` | `6` |
29
- | Border, separator | `300` | `7` |
30
- | Strong border, focus ring | `400` | `8` |
31
- | Solid fill | `500` | `9` |
32
- | Solid fill hover | `600` | `10` |
33
- | Low-contrast text | `700` | `11` |
34
- | High-contrast text | `900` | `12` |
35
-
36
- The two conventions differ in kind, not only in numbering:
37
-
38
- - **Radix defines its 12 steps by role.** Step 9 is "the solid fill" in every ramp and appearance. The dark scale is a separate ramp reusing the same numbers, so `--accent-9` is the fill in both and component CSS never changes.
39
- - **Tailwind defines its 11 steps by lightness.** `50` is light, `950` is dark. The mapping above therefore holds in light mode and inverts in dark, with the page background at `950` and high-contrast text at `50`. Components either swap step numbers per appearance or read a semantic token that swaps once.
40
-
41
- Match whichever the project uses. For a new system prefer Radix's model, because a role-defined step survives a theme change that a lightness-defined step does not. On Tailwind, keep `50`–`950` and put the role mapping in the semantic tier.
42
-
43
- Tailwind's 11 steps cover 12 roles, so some do double duty. Where the table repeats a step, the two roles are adjacent in practice and the collision is real. A design needing a subtle border and a component hover to be distinguishable needs a 12-step ramp.
44
-
45
- ## Neutrals
46
-
47
- A pure gray ramp is a perfectly good default. It sits under any accent hue without competing and never needs revisiting when the brand color changes.
48
-
49
- Tinting the neutral toward the accent hue is a stylistic option, not a correction. A trace of the accent, a few percent of its vividness, puts the greys in the same family as the accent rather than merely coexisting with it. Enough to measure, not enough to name. Neither choice reads as a mistake.
50
-
51
- Warm neutrals, hue toward orange, read approachable and editorial; cool ones, toward blue, read technical and precise. Whichever you pick, including none, hold it across the whole ramp. A warm gray border on a cool gray background is visible even when neither color is nameable alone.
52
-
53
- Neutrals carry the most roles, so they need the most steps. Never generate fewer neutral steps than accent steps.
54
-
55
- ## Status colors
56
-
57
- Convention constrains status hues before taste does. Red reads as danger, amber as warning, green as success. See the cultural exceptions in [color-usage.md](color-usage.md).
58
-
59
- Two rules govern them:
60
-
61
- - **Keep every status hue distinct from the accent.** If the brand is red, the danger ramp cannot also be red. Move danger toward a deeper crimson and check the two side by side, or the destructive and primary actions are the same button.
62
- - **Status ramps need fewer steps than the accent.** Most render four roles: a background, a border, a solid fill and text. Generate the full ramp only where the product styles status components across the whole range.
63
-
64
- Status color is never the only signal of a state change; pair it with an icon or text. `better-accessibility` owns that requirement.
65
-
66
- ## Auditing an existing palette
67
-
68
- Before restructuring a system, inventory it. Most codebases hold several times more colors than the design has decisions.
69
-
70
- 1. **Collect every literal.** Grep for hex, `rgb(`, `hsl(`, `oklch(` and the project's utility-class prefixes. Include SVG `fill`/`stroke`, chart configs and email templates. Colors hide outside stylesheets.
71
- 2. **Sort by perceived lightness within each hue family.** Duplicates surface immediately as near-identical neighbors.
72
- 3. **Collapse near-duplicates.** Two colors closer than about one ramp step are one color that drifted. Keep the one used most and retire the others. Never average them.
73
- 4. **Assign each survivor a role** from the table above. A color matching no role is a missing token or a mistake. Decide which, and say so in the finding.
74
- 5. **Count what is left.** More than one ramp per role above means the palette outgrew its structure, not that the product needs more color.
75
-
76
- Report the inventory before changing anything. Consolidating a palette changes rendered output on screens nobody asked you to touch, so it stays a proposal until the user accepts it.
@@ -1,88 +0,0 @@
1
- # Performance
2
-
3
- Transition specificity and GPU compositing hints.
4
-
5
- ## Transition only what changes
6
-
7
- Never use `transition: all` or Tailwind's `transition-all`. Always name the exact properties that change. Tailwind's bare `transition` maps to a curated list of colors, opacity, shadow and transforms rather than `all`, and naming what changes is still better.
8
-
9
- ### Why
10
-
11
- - `transition: all` forces the browser to watch every property for changes
12
- - Causes unexpected transitions on properties you didn't intend to animate (colors, padding, shadows)
13
- - Prevents browser optimizations
14
-
15
- ### CSS example
16
-
17
- ```css
18
- /* Good: only transition what changes */
19
- .button {
20
- transition-property: scale, background-color;
21
- transition-duration: 150ms;
22
- transition-timing-function: ease-out;
23
- }
24
-
25
- /* Bad: transition everything */
26
- .button {
27
- transition: all 150ms ease-out;
28
- }
29
- ```
30
-
31
- ### Tailwind
32
-
33
- ```tsx
34
- // Good: explicit properties
35
- <button className="transition-[scale,background-color] duration-150 ease-out">
36
-
37
- // Bad: transition all
38
- <button className="transition-all duration-150 ease-out">
39
- ```
40
-
41
- ### Tailwind `transition-transform` note
42
-
43
- `transition-transform` in Tailwind maps to `transition-property: transform, translate, scale, rotate`, covering every transform-related property rather than only `transform`. Use it when animating transforms alone. For several non-transform properties, use the bracket syntax `transition-[scale,opacity,filter]`.
44
-
45
- ## Use `will-change` sparingly
46
-
47
- `will-change` hints the browser to pre-promote an element to its own GPU compositing layer. Without it the browser promotes only when the animation starts, and that one-time promotion can cause a micro-stutter on the first frame.
48
-
49
- It helps most for `scale`, `rotation` and movement through `transform`. For other properties it does little, because the browser cannot composite them on the GPU anyway.
50
-
51
- ### Rules
52
-
53
- ```css
54
- /* Good: specific property that benefits from GPU compositing */
55
- .animated-card {
56
- will-change: transform;
57
- }
58
-
59
- /* Good: multiple compositor-friendly properties */
60
- .animated-card {
61
- will-change: transform, opacity;
62
- }
63
-
64
- /* Bad: never use will-change: all */
65
- .animated-card {
66
- will-change: all;
67
- }
68
-
69
- /* Bad: properties that can't be GPU-composited anyway */
70
- .animated-card {
71
- will-change: background-color, padding;
72
- }
73
- ```
74
-
75
- ### Useful properties
76
-
77
- | Property | GPU-compositable | Worth using `will-change` |
78
- | --- | --- | --- |
79
- | `transform` | Yes | Yes |
80
- | `opacity` | Yes | Yes |
81
- | `filter` (blur, brightness) | Yes | Yes |
82
- | `clip-path` | Newer Chromium only | Rarely; not reliable cross-browser |
83
- | `top`, `left`, `width`, `height` | No | No |
84
- | `background`, `border`, `color` | No | No |
85
-
86
- ### When to skip
87
-
88
- Modern browsers optimize well on their own. Add `will-change` only when you see first-frame stutter, which Safari benefits from most. Never add it preemptively to every animated element, since each extra compositing layer costs memory.
@@ -1,76 +0,0 @@
1
- # The picker
2
-
3
- The control that switches variants. Its appearance is not a design decision, because it sits on top of the thing being judged. Build the spec below and leave it alone.
4
-
5
- ## Deliberately outside the design system
6
-
7
- Never style the picker with the project's tokens, fonts, or colors. One that looks native to the product becomes part of what you are looking at, and then you are judging the harness.
8
-
9
- One dark neutral surface, the system font stack and no project variables. Dark reads as chrome over both light and dark pages, which is why it does not follow the theme.
10
-
11
- ## Behavior
12
-
13
- - It sets a `variant` search param and reads the active variant back from it, so the URL is the source of truth and every variant a link.
14
- - Left and right arrows step through the set. Number keys jump to one directly.
15
- - The active item carries `aria-current="true"`, and the container carries a label.
16
- - Switching is instant. Flipping is the run's highest-frequency action, so `better-ui`'s motion restraint gives it no transition.
17
- - It survives a resize, so you can hold a variant and drag the window rather than reloading per width.
18
-
19
- ## Structure
20
-
21
- One button per variant, in the order they were named. Add a replay button only where a variant has an entrance worth re-triggering.
22
-
23
- ```html
24
- <nav class="variant-picker" aria-label="Variants">
25
- <button type="button" data-variant="quiet" aria-current="true">Quiet</button>
26
- <button type="button" data-variant="editorial">Editorial</button>
27
- <button type="button" data-variant="dense">Dense</button>
28
- </nav>
29
- ```
30
-
31
- ## Placement and styling
32
-
33
- Fixed, bottom centre, above everything the page can stack. Keep it clear of the piece under judgement. Where the variants live at the bottom of the viewport, move the picker to top centre and say so.
34
-
35
- ```css
36
- .variant-picker {
37
- position: fixed;
38
- bottom: 24px;
39
- left: 50%;
40
- translate: -50% 0;
41
- z-index: 2147483647;
42
- display: flex;
43
- gap: 2px;
44
- padding: 4px;
45
- border-radius: 999px;
46
- background: rgb(20 20 20 / 0.9);
47
- box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.1), 0 8px 24px rgb(0 0 0 / 0.25);
48
- font: 13px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
49
- user-select: none;
50
- }
51
-
52
- .variant-picker button {
53
- padding: 7px 14px;
54
- border: 0;
55
- border-radius: 999px;
56
- background: none;
57
- color: rgb(255 255 255 / 0.6);
58
- cursor: pointer;
59
- }
60
-
61
- .variant-picker button:hover {
62
- color: rgb(255 255 255 / 0.85);
63
- }
64
-
65
- .variant-picker button[aria-current="true"] {
66
- background: rgb(255 255 255 / 0.14);
67
- color: rgb(255 255 255);
68
- }
69
-
70
- .variant-picker button:focus-visible {
71
- outline: 2px solid rgb(255 255 255 / 0.7);
72
- outline-offset: 2px;
73
- }
74
- ```
75
-
76
- In a framework, keep the class names and the structure and change only the rendering syntax.