Every SKILL.md already declared the new name — name: frames, frames-cli, frames-core, and so on — but the directories were never moved, so the tree carried frames-* in content and hyperframes-* on disk. Everything that resolves a skill by path missed: the core-skill list, the plugin marketplace pin, and the docs the CLI reads at runtime. Eight tests failed on main because the files they open do not exist. The directories now match what the files say they are, and the guide the claude-design contract reads takes the name that contract already used.
6.4 KiB
name, description, metadata
| name | description | metadata | ||
|---|---|---|---|---|
| spring-pop-entrance | The canonical entrance pop — an element (or staggered group) arrives by scaling 0 → 1 on a smooth long-tail settle (power3 default); bouncy overshoot is a rare, explicitly-playful exception. fromTo so it's correct at t=0 under seek. |
|
Spring-Pop Entrance
Smooth beats bouncy. This entrance defaults to a smooth long-tail settle —
power3.out(orexpo.outfor a faster front) — that decelerates cleanly into the resting size with no overshoot. Bouncyback.outis the #1 instant turn-off in agent-made videos and is almost never executed well; it is a rare, explicitly-playful exception (consumer / fun brand), never the default. When unsure, settle smoothly.
THE entrance primitive: an element (or staggered group) arrives by springing from nothing — scale: 0 → 1, optional small y rise — and settles without bouncing. This is arrival, not reaction: distinct from press-release-spring.md (a click/press → release feedback chain on an element that already rests on screen). Many blueprints used to borrow that rule to fake an entrance; reach for this instead.
How It Works
One fromTo carries the whole arrival: from { scale: 0, opacity: 0 } (explicit, so t=0 is correct under seek) to { scale: 1, opacity: 1, ease: "power3.out" }. For a group, the same fromTo runs per element at i * STAGGER, capped so the group reads as one arriving beat. The scale grow is load-bearing; the y rise is garnish — drop everything else and it must still read as a clean entrance. Let the ease produce the settle: never hand-key a scale: 1.1 mid-state (it double-bounces against the curve).
Recipe
<!-- inside a standard scene clip (frames-core) -->
<div class="pop-hero" id="hero">{heroLabel}</div>
<div class="pop-grid">
<div class="pop-item">{itemA}</div>
<div class="pop-item">{itemB}</div>
<div class="pop-item">{itemC}</div>
</div>
.pop-hero,
.pop-item {
transform-origin: 50% 50%; /* in-place pop; move to the source point for the anchored variation */
will-change: transform;
}
.pop-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: GRID_GAP;
place-items: center;
}
// Single hero pop — smooth long-tail settle, no overshoot.
tl.fromTo(
"#hero",
{ scale: 0, opacity: 0 },
{ scale: 1, opacity: 1, duration: POP_DUR, ease: "power3.out" },
ENTRY_AT,
);
// Staggered group pop — one arriving beat.
gsap.utils.toArray(".pop-item").forEach((el, i) => {
tl.fromTo(
el,
{ scale: 0, opacity: 0, y: Y_RISE },
{ scale: 1, opacity: 1, y: 0, duration: POP_DUR, ease: "power3.out" },
GROUP_ENTRY_AT + i * STAGGER,
);
});
Variations
- Calm settle (premium / enterprise):
power3.out, no rotation,Y_RISE0–12px — a weighted, confident landing for a hero wordmark or product shot. - Firm settle (everyday default):
power3.outorexpo.outfor a punchier front,Y_RISE~24px — cards, icons, callouts. - Exact-physics settle: when the settle IS the shot, swap the ease for
springEase({ response: 0.4 })(critically damped) from../adapters/gsap-easing-and-stagger.md→ Spring Eases; takedurationfrom the helper. - Origin-anchored pop: a callout growing out of a specific point (marker, pointer tip) sets
transform-originto that point (e.g.0% 100%) soscale: 0 → 1reads as "emerging from the source", not "inflating in place". - Pop into a held slot: land the pop and hold still — no idle loop baked into the entrance. If the held frame genuinely needs life, hand off to sine-wave-loop.md for subtle jitter on a separate later tween; prefer revealing the next element on its VO cue.
- Bouncy pop (RARE — explicitly-playful only): swap the ease for
back.out(OVERSHOOT)and optionally settle a smallrotation: ROT_FROM → 0so elements look hand-placed. Only for a deliberately playful register — never product / enterprise / serious tone:
tl.fromTo(
el,
{ scale: 0, opacity: 0, rotation: ROT_FROM },
{ scale: 1, opacity: 1, rotation: 0, duration: POP_DUR, ease: `back.out(${OVERSHOOT})` },
GROUP_ENTRY_AT + i * STAGGER,
);
Even here keep OVERSHOOT ≤ ~2 — past that it reads as cartoon wobble. Better still: the baked spring at dampingFraction: 0.6–0.7 (same adapters doc) gives ~5–10% overshoot that reads physical where back.out reads cartoon.
Values
| token | range | notes |
|---|---|---|
| EASE | power3.out default; expo.out punchier |
back.out(OVERSHOOT) only in the playful variant |
| POP_DUR | 0.4–0.7s | shorter = tight snap; hero must be visible by t ≤ 0.5s |
| STAGGER | 0.04–0.08s | min(0.06, 0.5 / ITEM_COUNT) — self-caps the window |
| ITEM_COUNT | 3–9 | >9 makes the stagger vanish — switch to a wipe/sweep reveal |
| Y_RISE | 0–32px | small; never large enough to read as a slide-up |
| ROT_FROM | −10°–+10° | playful variant only; alternate sign by index (i % 2 ? 6 : -6) |
| ENTRY_AT | 0–0.4s | a beat of quiet, but keep the subject landing by t ≤ 0.5s |
Critical Constraints
- Default ease
power3.out(no overshoot);back.outonly in the explicitly-playful variant, and thereOVERSHOOT ≤ ~2. ITEM_COUNT × STAGGER ≤ ~0.5s— the group must land inside one beat.- Entrances state the collapsed from-state in
fromTo— never rely on a CSS-hidden start (it renders visible before the tween claims it under seek). transform-origin: 50% 50%for an in-place pop; the source point only for the anchored variation.- This is a finite arrival — idle motion on a held element is a separate, later
sine-wave-looptween.
See also
center-outward-expansion (pop while radiating to slots) · press-release-spring (the click-feedback counterpart) · sine-wave-loop (post-arrival jitter, sparingly).