@ericrisco/rsc 1.0.33 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/manifest.json +45 -2
- package/package.json +1 -1
- package/scripts/doctor.js +5 -0
- package/scripts/lib/design-identity.js +117 -0
- package/scripts/lib/domains.js +1 -1
- package/scripts/lib/recommend.js +2 -0
- package/skills/animate/SKILL.md +623 -0
- package/skills/design/SKILL.md +2 -1
- package/skills/design-dna/PROMPT.md +211 -0
- package/skills/design-dna/SKILL.md +158 -0
- package/skills/design-dna/design-dna.schema.json +230 -0
- package/skills/design-dna/evals/README.md +64 -0
- package/skills/design-dna/evals/cases.yaml +68 -0
- package/skills/design-dna/references/method.md +436 -0
- package/skills/design-dna/scripts/emit.py +164 -0
- package/skills/design-dna/templates/PROMPT.md.tmpl +42 -0
- package/skills/design-dna/templates/SKILL.md.tmpl +42 -0
- package/skills/design-dna/templates/check.py.tmpl +143 -0
- package/skills/design-eng/SKILL.md +19 -655
- package/skills/design-loop/SKILL.md +152 -0
- package/skills/design-loop/evals/README.md +56 -0
- package/skills/design-loop/evals/cases.yaml +60 -0
- package/skills/review-animations/SKILL.md +51 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-loop
|
|
3
|
+
description: "Use when something must be built well and there is a real reference it should beat: turn what makes the reference good into measured mechanisms, then run a builder and three fresh-context critics until all three pass. Fires on 'design loop', 'make it as good as <site>', 'it looks generic'. NOT keeping an already-won look (that is `design-dna`)."
|
|
4
|
+
tags: [design, critique, loop, reference, quality, convergence]
|
|
5
|
+
recommends: [design, design-dna, marketing, nextjs]
|
|
6
|
+
origin: risco
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Design Loop — the front door of the design area
|
|
10
|
+
|
|
11
|
+
*A reference you can open, mechanisms you can check, and three judges who did not build the thing.*
|
|
12
|
+
|
|
13
|
+
This is where a design request **enters**. It owns the method: the bar, the judges, the rounds. It
|
|
14
|
+
does not own the visual system — `../design/SKILL.md` does, and this skill invokes it as the builder.
|
|
15
|
+
|
|
16
|
+
**Why the method and not a rubric.** A rubric scored by whoever built the piece measures *intent*,
|
|
17
|
+
because the builder knows what they were going for and so they see it there. And scores drift upward
|
|
18
|
+
every round: a 7 that becomes an 8 with nothing changed is how a loop declares itself finished early.
|
|
19
|
+
Binary verdicts from someone who did not build it are the fix for both.
|
|
20
|
+
|
|
21
|
+
Four phases. Do not skip ahead, and do not start building during 1 to 3.
|
|
22
|
+
|
|
23
|
+
## Phase 1 — Interview
|
|
24
|
+
|
|
25
|
+
Ask exactly these three, together, then stop and wait.
|
|
26
|
+
|
|
27
|
+
1. What are you building, and how long or how big?
|
|
28
|
+
2. Name something that already does this brilliantly — a site, a video, a doc, anything I can open.
|
|
29
|
+
If nothing comes to mind, say skip.
|
|
30
|
+
3. Any files I should work from? Design system, brand doc, script, existing draft.
|
|
31
|
+
|
|
32
|
+
**A vague bar is the number one reason this method fails.** If they name something vague ("Apple's
|
|
33
|
+
website", "good SaaS design"), push once for the specific page or file: a critic with no concrete
|
|
34
|
+
reference invents the comparison and approves everything on round one.
|
|
35
|
+
|
|
36
|
+
On *skip*, propose three candidate bars, one line each on why, and wait. No answer → take the
|
|
37
|
+
hardest one and say so.
|
|
38
|
+
|
|
39
|
+
## Phase 2 — Preflight
|
|
40
|
+
|
|
41
|
+
A check, not a question. Run it before any work and report in one block.
|
|
42
|
+
|
|
43
|
+
- **Fetch the bar now.** Screenshot the URL or read the file. Blocked or missing → say so, ask for
|
|
44
|
+
another. Never substitute a description from memory.
|
|
45
|
+
- **Confirm you can render our output**: screenshots for a site, a filmstrip for animation, a PDF
|
|
46
|
+
render for a doc.
|
|
47
|
+
- **Name the generation tools the goal needs** (image, video, voice) and confirm they are connected.
|
|
48
|
+
- **Confirm the input files exist**: design system, brand doc, script.
|
|
49
|
+
- **Read the harness identity if it exists** — `02-DOCS/wiki/brand/`, reached from the root
|
|
50
|
+
`CLAUDE.md` `## Brand & voice` section, the same place `design`, `marketing` and
|
|
51
|
+
`presentations` read. A bar from outside cannot silently overrule the identity this project
|
|
52
|
+
already committed to: if the reference contradicts it, say which rule conflicts and let the
|
|
53
|
+
user decide which one wins. If no identity exists yet, say so — this run is what creates it.
|
|
54
|
+
|
|
55
|
+
Then print what is working, what is missing, and **which critic goes blind** if something is
|
|
56
|
+
missing. Never carry on quietly with a critic that cannot see — a verdict from a judge who cannot
|
|
57
|
+
see the thing is worse than no verdict, because it looks like evidence.
|
|
58
|
+
|
|
59
|
+
## Phase 3 — Teardown
|
|
60
|
+
|
|
61
|
+
Read the reference properly and write **5 to 7 mechanisms** to `bar.md`.
|
|
62
|
+
|
|
63
|
+
Mechanisms, not adjectives. "Feels premium" is useless. These are useful:
|
|
64
|
+
|
|
65
|
+
- headline is 5x body size, three type sizes total
|
|
66
|
+
- one accent colour, used at most twice per screen
|
|
67
|
+
- motion always resolves in one direction
|
|
68
|
+
- nothing animates for under 400ms
|
|
69
|
+
- whitespace above the fold is at least 40% of the frame
|
|
70
|
+
|
|
71
|
+
Every line must be something a critic can check by looking. Show `bar.md` to the user before
|
|
72
|
+
continuing — and where a mechanism contradicts the harness identity, mark the conflict rather
|
|
73
|
+
than resolving it silently in favour of the reference.
|
|
74
|
+
|
|
75
|
+
## Phase 4 — Loop
|
|
76
|
+
|
|
77
|
+
Split the goal into the smallest pieces that can be improved and judged on their own. You choose
|
|
78
|
+
them. Keep it to three or four unless told otherwise: **every extra piece multiplies the run, and so
|
|
79
|
+
does every extra round.**
|
|
80
|
+
|
|
81
|
+
For each piece: fan out a builder, then three critics, each with fresh context and no knowledge of
|
|
82
|
+
how the builder worked.
|
|
83
|
+
|
|
84
|
+
- **Brief critic** — judges against the stated goal only. Does it do the thing? Ignore aesthetics.
|
|
85
|
+
- **System critic** — judges against the project's design system only. Objective adherence.
|
|
86
|
+
- **Craft critic** — judges against `bar.md` and rendered output only. Put ours next to the
|
|
87
|
+
reference blind, labels stripped, say which is better, name the single biggest gap.
|
|
88
|
+
|
|
89
|
+
Write each critic's brief yourself, adapted to this goal. Do not reuse generic wording across
|
|
90
|
+
different goals.
|
|
91
|
+
|
|
92
|
+
### Rules
|
|
93
|
+
|
|
94
|
+
- **Critics judge rendered output, never the code.** Reading the implementation makes a critic
|
|
95
|
+
evaluate intent instead of result.
|
|
96
|
+
- **Binary verdicts, not scores.** Scores drift upward every round.
|
|
97
|
+
- **Critics are harsh, and harshness has a floor.** A critic has explicit permission to say a piece
|
|
98
|
+
passes. A judge under standing orders to find fault will manufacture one, and then "all three must
|
|
99
|
+
pass" is a door that recedes as you approach it.
|
|
100
|
+
- **All three must pass.** Any fail goes back to the builder with the single biggest gap named — one,
|
|
101
|
+
not a list.
|
|
102
|
+
- **No fixed round count.** The exit is winning, or the user stopping the run, or the halt below.
|
|
103
|
+
|
|
104
|
+
### The halt — how this loop is allowed to end
|
|
105
|
+
|
|
106
|
+
Fresh-context critics cannot see the gap history, so nothing arbitrates across rounds. Left alone,
|
|
107
|
+
two incompatible gaps ("more air" / "more density") make the builder ping-pong forever, and the only
|
|
108
|
+
brake is a human watching. Keep the gap history and use it:
|
|
109
|
+
|
|
110
|
+
> **The same biggest gap named twice for the same piece halts that piece.** Put the two competing
|
|
111
|
+
> demands side by side and ask the user to decide. Do not spend a third round on it.
|
|
112
|
+
|
|
113
|
+
This is not a nicety. A loop whose declared exit is "all three pass" and which cannot detect that it
|
|
114
|
+
will never get there is a gate that cannot close.
|
|
115
|
+
|
|
116
|
+
### Progress and cost
|
|
117
|
+
|
|
118
|
+
Keep a live progress page: piece status, each critic's verdict, gap history, round count.
|
|
119
|
+
|
|
120
|
+
There is **no reliable self-reported token cost, so do not show one.** Show round count and pieces
|
|
121
|
+
instead. If the user names a ceiling, treat it as a checkpoint: pause and ask before passing it, and
|
|
122
|
+
tell them plainly that the real brake is them watching and stopping the run.
|
|
123
|
+
|
|
124
|
+
## When the piece wins
|
|
125
|
+
|
|
126
|
+
Hand the winner to `../design-dna/SKILL.md` to codify it: measured ratios, bans and tests that can
|
|
127
|
+
fail, so piece eight still sits beside piece one as a set. Winning once and not writing down why is
|
|
128
|
+
how the look drifts back to generic by the fifth piece.
|
|
129
|
+
|
|
130
|
+
## What breaks this
|
|
131
|
+
|
|
132
|
+
| Symptom | Cause | Fix |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| Everything approved on round one | Vague bar | Push for the specific page or file |
|
|
135
|
+
| Approvals that do not survive a second look | Builder judged its own work | Critics need fresh context |
|
|
136
|
+
| Verdicts creep upward each round | Scores instead of binaries | Binary job, not a score |
|
|
137
|
+
| Loop never exits | No halt on a repeated gap | Apply the halt above |
|
|
138
|
+
| Loop exits with the piece still weak | Fixed round count | The exit is winning |
|
|
139
|
+
| Obeys the letter, misses the point | Over-specifying | Every extra instruction is one fewer decision the model makes with its own judgment |
|
|
140
|
+
|
|
141
|
+
## Hand-offs
|
|
142
|
+
|
|
143
|
+
- **The visual system, brand grounding, page composition** → `../design/SKILL.md`. It is the builder
|
|
144
|
+
this loop invokes; it stays reachable directly when there is no bar to beat and no loop to run.
|
|
145
|
+
- **Codifying the winner into a permanent identity** → `../design-dna/SKILL.md`.
|
|
146
|
+
- **The words** → `../marketing/SKILL.md`. **The build** → `../nextjs/SKILL.md`.
|
|
147
|
+
- **Motion craft, and routing among the frontend craft siblings** → `../design-eng/SKILL.md`.
|
|
148
|
+
- **"Show me a few versions and I'll pick"** → `../prototype/SKILL.md`. That is selection among
|
|
149
|
+
variants; this is convergence against a bar.
|
|
150
|
+
- **SDD gate.** This skill runs a method; it does not outrank the chain. If the request is a new
|
|
151
|
+
feature or a non-trivial behaviour change in a real app, `../specify/SKILL.md` runs first, then
|
|
152
|
+
`plan`, then the loop builds what was approved.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Eval harness — `design-loop` skill
|
|
2
|
+
|
|
3
|
+
Agent-run eval, not a shell script. The cases in `cases.yaml` are fed to a Claude Code agent and
|
|
4
|
+
graded by inspection. The "harness" is the procedure below plus a human (or a judge agent) checking
|
|
5
|
+
outputs against the rubrics.
|
|
6
|
+
|
|
7
|
+
## What's under test
|
|
8
|
+
|
|
9
|
+
1. **Triggering** — does the loop fire when a goal comes with a real reference to beat, and stay
|
|
10
|
+
quiet on the near-misses that belong to a sibling? The expensive confusions are `design` (visual
|
|
11
|
+
system, no bar), `prototype` (variants picked by preference, no bar) and `design-dna` (the winner
|
|
12
|
+
already exists).
|
|
13
|
+
2. **Capability** — when it fires, does it hold the three phases it is easiest to skip, and does its
|
|
14
|
+
loop actually terminate?
|
|
15
|
+
|
|
16
|
+
## A. Triggering accuracy
|
|
17
|
+
|
|
18
|
+
Run each `should_trigger` prompt in a session with the skill installed. It must activate. Run each
|
|
19
|
+
`should_not_trigger` prompt: it must stay quiet and the named `route_to` sibling must be the one that
|
|
20
|
+
answers.
|
|
21
|
+
|
|
22
|
+
The two cases worth watching, because they are where the boundary really is:
|
|
23
|
+
|
|
24
|
+
- *"Show me three versions and I'll pick"* → `prototype`. Selection is not convergence. The user is
|
|
25
|
+
the judge and no bar exists.
|
|
26
|
+
- *"Codify this into a reusable style"* → `design-dna`. Nothing left to converge; this is the
|
|
27
|
+
downstream half.
|
|
28
|
+
|
|
29
|
+
## B. Capability
|
|
30
|
+
|
|
31
|
+
The three scenarios are the three things this skill exists to do and the three it is cheapest to
|
|
32
|
+
fake:
|
|
33
|
+
|
|
34
|
+
1. **The vague bar and the blind critic.** A bar of "Apple's website" must be pushed back on once,
|
|
35
|
+
and a missing render capability must be declared as *which critic goes blind* — not absorbed
|
|
36
|
+
silently. A critic that cannot see, still voting, is the failure this phase prevents.
|
|
37
|
+
2. **Termination.** The scenario hands it an oscillation: air, then density, then air again. The
|
|
38
|
+
skill must halt the piece and surface the two competing demands. **This is the case that matters
|
|
39
|
+
most**: everything else in the skill is judgement, but a loop that cannot detect it will never
|
|
40
|
+
converge is a gate that cannot close, and the constitution's P2 forbids exactly that.
|
|
41
|
+
3. **Hand-off on winning.** Four more pages after a win must go through `design-dna`, not four more
|
|
42
|
+
loops. Re-deriving a style you already won is how the set stops looking like a set.
|
|
43
|
+
|
|
44
|
+
## Grading
|
|
45
|
+
|
|
46
|
+
A case passes when every `must_include` line is observably present in the agent's output or actions.
|
|
47
|
+
Partial credit is not useful here: the mechanisms are the skill, and a run that keeps the prose but
|
|
48
|
+
drops the halt has kept the part that costs nothing.
|
|
49
|
+
|
|
50
|
+
## Known limits of this eval
|
|
51
|
+
|
|
52
|
+
- **Scores vs binaries** and **critics judging rendered output only** are properties of a real
|
|
53
|
+
multi-round run. A single-turn eval can check that the skill *states* them; it cannot prove a
|
|
54
|
+
four-round run honoured them. Verifying that needs a live run against a real reference.
|
|
55
|
+
- The halt is checked from a described history, not a real one. It tests the rule, not the
|
|
56
|
+
bookkeeping that feeds it.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
skill: design-loop
|
|
2
|
+
|
|
3
|
+
should_trigger:
|
|
4
|
+
- prompt: "Build me a landing page for our analytics product that's as good as linear.app — here's the URL."
|
|
5
|
+
why: "Goal plus a named, openable reference to beat. This is the skill's core shape: a bar exists and the work must clear it."
|
|
6
|
+
- prompt: "Our homepage looks generic. Loop it against stripe.com until it actually wins."
|
|
7
|
+
why: "'Looks generic' plus a named bar plus explicit looping — three of the skill's stated triggers in one sentence."
|
|
8
|
+
- prompt: "/design-loop"
|
|
9
|
+
why: "Explicit invocation by name; the skill must run its own interview rather than asking what the user wants in free form."
|
|
10
|
+
- prompt: "I want a pitch deck that holds up next to this one — attaching their PDF."
|
|
11
|
+
why: "Non-obvious because the medium is not web. The method is medium-agnostic: a deck with an openable reference is the same loop, and the craft critic renders to PDF instead of screenshots."
|
|
12
|
+
- prompt: "Run the critic loop on the pricing page and don't stop until it beats the reference."
|
|
13
|
+
why: "Names the mechanism (critic loop) and the exit condition (beating the reference) rather than the outcome."
|
|
14
|
+
- prompt: "Quiero que esta página le gane a la de vercel. Dale vueltas hasta que gane."
|
|
15
|
+
why: "Non-English phrasing with no keyword overlap with the description; the trigger is the semantic shape — a reference to beat plus iteration until it wins."
|
|
16
|
+
- prompt: "This animation feels cheap compared to the one on their site. Can you get it to that level?"
|
|
17
|
+
why: "Non-obvious: reads like a motion request, but a named reference plus a quality gap is a bar to converge against. The loop owns convergence and hands the motion implementation to the craft siblings."
|
|
18
|
+
|
|
19
|
+
should_not_trigger:
|
|
20
|
+
- prompt: "This page came out great. Codify it into a reusable style so my next five pages match it."
|
|
21
|
+
route_to: "design-dna"
|
|
22
|
+
why: "The winner already exists; nothing left to converge. Capturing an identity is the downstream half of the pipe, not the loop."
|
|
23
|
+
- prompt: "Pick a colour palette and type pairing for my product and give me the Tailwind tokens."
|
|
24
|
+
route_to: "design"
|
|
25
|
+
why: "Visual system work with no reference to beat and nothing to judge. `design` stays directly reachable exactly for this."
|
|
26
|
+
- prompt: "Show me three versions of this button and I'll pick the one I like."
|
|
27
|
+
route_to: "prototype"
|
|
28
|
+
why: "Selection among variants by human preference, not convergence against a measured bar. The user is the judge and there is no reference."
|
|
29
|
+
- prompt: "Review the motion in this diff and tell me what's off."
|
|
30
|
+
route_to: "review-animations"
|
|
31
|
+
why: "One diff, motion-specific, no reference and no build-then-judge rounds. Reviewing is not looping."
|
|
32
|
+
- prompt: "Write the hero headline and value prop for our developer-tool site."
|
|
33
|
+
route_to: "marketing"
|
|
34
|
+
why: "The words, not the bar. `voice` constrains copy in this pipe; it does not write it."
|
|
35
|
+
- prompt: "Set up the Next.js App Router routing and server actions for these pages."
|
|
36
|
+
route_to: "nextjs"
|
|
37
|
+
why: "Pure build mechanics with no design judgement involved at all."
|
|
38
|
+
|
|
39
|
+
capability:
|
|
40
|
+
- scenario: "User asks: 'Make our homepage as good as Apple's website.' (Vague bar. The repo has a design system at design-system.md but no way to render output to screenshots.)"
|
|
41
|
+
must_include:
|
|
42
|
+
- "Pushes back ONCE for the specific page or file rather than accepting 'Apple's website' — names that a vague bar is the top failure mode because a critic with no concrete reference invents the comparison and approves everything on round one."
|
|
43
|
+
- "Runs preflight BEFORE any work and reports it as one block: fetches the bar, checks render capability, checks input files."
|
|
44
|
+
- "Explicitly names that the CRAFT critic goes blind because output cannot be rendered — does not quietly proceed with three critics when only two can see."
|
|
45
|
+
- "Does not start building during the interview, preflight or teardown phases."
|
|
46
|
+
- "Writes 5-7 mechanisms to bar.md as checkable measurements (ratios, coverage, percentages, absences) and shows them to the user before continuing; rejects adjectives like 'feels premium' as mechanisms."
|
|
47
|
+
- "Uses binary verdicts, never numeric scores, and states that scores drift upward every round."
|
|
48
|
+
- "Keeps critics on rendered output only, never the implementation, and gives each fresh context with no knowledge of how the builder worked."
|
|
49
|
+
- scenario: "The loop is running on a hero section. Round 2's craft critic names 'not enough breathing room above the fold' as the biggest gap. Round 3's craft critic names 'the hero feels empty, needs more density' as the biggest gap. Round 4 would name 'not enough breathing room' again."
|
|
50
|
+
must_include:
|
|
51
|
+
- "HALTS that piece instead of starting another round — detects that the same biggest gap has been named twice for the same piece."
|
|
52
|
+
- "Puts the two competing demands side by side (more air vs more density) and asks the user to decide, rather than picking one itself or averaging them."
|
|
53
|
+
- "Does not present the halt as a failure of the loop; it is the declared exit for non-convergence."
|
|
54
|
+
- "Shows round count and pieces rather than claiming a token cost, and states that no reliable self-reported token cost exists."
|
|
55
|
+
- "Keeps the gap history that made the detection possible, as part of the live progress page."
|
|
56
|
+
- scenario: "A piece has cleared all three critics and the user says 'perfect, now do the other four pages'."
|
|
57
|
+
must_include:
|
|
58
|
+
- "Hands the winner to design-dna to codify it into a permanent identity before building the remaining pieces, rather than re-running the loop from scratch four more times."
|
|
59
|
+
- "Names why: winning once without writing down the mechanisms is how the look drifts back to generic by the fifth piece."
|
|
60
|
+
- "Does not merge the won style with any other identity."
|
|
@@ -135,3 +135,54 @@ Adapted for the rsc catalog from **[emilkowalski/skills](https://github.com/emil
|
|
|
135
135
|
[Sonner](https://sonner.emilkowal.ski), [Vaul](https://vaul.emilkowal.ski) and
|
|
136
136
|
[animations.dev](https://animations.dev). The craft bar here is his; the routing, gates and evals
|
|
137
137
|
that make it an rsc skill are not. Nothing in this body is a substitute for his course.
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
# Craft reference, inherited from the umbrella
|
|
141
|
+
|
|
142
|
+
*Moved here from `design-eng` (spec: `design-area-cleanup`), which routes and no longer teaches.
|
|
143
|
+
This is the same material by the same author; where it overlaps a rule stated above, the above is
|
|
144
|
+
the summary and this is the reasoning.*
|
|
145
|
+
|
|
146
|
+
## Review Format (Required)
|
|
147
|
+
|
|
148
|
+
When reviewing UI code, you MUST use a markdown table with Before/After columns. Do NOT use a list with "Before:" and "After:" on separate lines. Always output an actual markdown table like this:
|
|
149
|
+
|
|
150
|
+
| Before | After | Why |
|
|
151
|
+
| --- | --- | --- |
|
|
152
|
+
| `transition: all 300ms` | `transition: transform 200ms ease-out` | Specify exact properties; avoid `all` |
|
|
153
|
+
| `transform: scale(0)` | `transform: scale(0.95); opacity: 0` | Nothing in the real world appears from nothing |
|
|
154
|
+
| `ease-in` on dropdown | `ease-out` with custom curve | `ease-in` feels sluggish; `ease-out` gives instant feedback |
|
|
155
|
+
| No `:active` state on button | `transform: scale(0.97)` on `:active` | Buttons must feel responsive to press |
|
|
156
|
+
| `transform-origin: center` on popover | `transform-origin: var(--transform-origin)` | Popovers should scale from their trigger (not modals — modals stay centered) |
|
|
157
|
+
|
|
158
|
+
Wrong format (never do this):
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
Before: transition: all 300ms
|
|
162
|
+
After: transition: transform 200ms ease-out
|
|
163
|
+
────────────────────────────
|
|
164
|
+
Before: scale(0)
|
|
165
|
+
After: scale(0.95)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Correct format: A single markdown table with | Before | After | Why | columns, one row per issue found. The "Why" column briefly explains the reasoning.
|
|
169
|
+
|
|
170
|
+
## Review Checklist
|
|
171
|
+
|
|
172
|
+
When reviewing UI code, check for:
|
|
173
|
+
|
|
174
|
+
| Issue | Fix |
|
|
175
|
+
| ------------------------------------------ | ---------------------------------------------------------------- |
|
|
176
|
+
| `transition: all` | Specify exact properties: `transition: transform 200ms ease-out` |
|
|
177
|
+
| `scale(0)` entry animation | Start from `scale(0.95)` with `opacity: 0` |
|
|
178
|
+
| `ease-in` on UI element | Switch to `ease-out` or custom curve |
|
|
179
|
+
| `transform-origin: center` on popover | Set to trigger location or use Base UI's `var(--transform-origin)` (modals are exempt — keep centered) |
|
|
180
|
+
| Animation on keyboard action | Remove animation entirely |
|
|
181
|
+
| Duration > 300ms on UI element | Reduce to 150-250ms |
|
|
182
|
+
| Hover animation without media query | Add `@media (hover: hover) and (pointer: fine)` |
|
|
183
|
+
| Keyframes on rapidly-triggered element | Use CSS transitions for interruptibility |
|
|
184
|
+
| Framer Motion `x`/`y` props under load | Use `transform: "translateX()"` for hardware acceleration |
|
|
185
|
+
| Same enter/exit transition speed | Make exit faster than enter (e.g., enter 2s, exit 200ms) |
|
|
186
|
+
| Elements all appear at once | Add stagger delay (30-80ms between items) |
|
|
187
|
+
|
|
188
|
+
---
|