plans/issues/issue-2580.md
attrX & co. typecheck in AnimationSequence, pin with a type test, close #2580Executor instructions: Follow this plan step by step. Run every verification command and confirm the expected result before moving on. If anything in "STOP conditions" occurs, stop and report. When done, update the status row for this plan in
plans/issues/README.md.Drift check (run first):
gh api repos/motiondivision/motion/issues/2580 --jq .state→ expectedopen. If closed, mark the README row DONE and stop.
DOMKeyframesDefinition composition)42bfbe3ed, 2026-06-11Reported 2024: using SVG forced-attr properties (attrX, attrY,
attrScale) inside an AnimationSequence segment —
animate([[scope.current, { attrX: 100 }]]) — worked at runtime but raised
a TypeScript error. Verified fixed at planning time: the exact repro
compiles cleanly against the current built d.ts (exit 0, see verification
in "Current state"). The types gained SVGForcedAttrKeyframesDefinition
inside DOMKeyframesDefinition, which DOMSegment uses. What's missing is
a regression type test so a future type refactor can't silently regress it,
and the issue should be closed.
packages/motion-dom/src/animation/types.ts:565-577:
export type SVGForcedAttrKeyframesDefinition = {
[K in keyof SVGForcedAttrProperties]?: ValueKeyframesDefinition
}
...
export type DOMKeyframesDefinition = StyleKeyframesDefinition &
SVGKeyframesDefinition &
SVGPathKeyframesDefinition &
SVGForcedAttrKeyframesDefinition &
VariableKeyframesDefinition
SVGForcedAttrProperties { attrX?: number; attrY?: number; attrScale?: number }
at types.ts:725-729.packages/framer-motion/src/animation/sequence/types.ts:76 —
export type DOMSegment = [ElementOrSelector, DOMKeyframesDefinition]
(imported from motion-dom).packages/framer-motion/dist/index.d.ts via a paths
mapping):
import { animate } from "framer-motion"
declare const el: SVGTextElement
animate([[el, { attrX: 100 }, { duration: 1 }]])
animate(el, { attrX: 100 })
tsc --strict --noEmit exit 0, no errors.tsd; type regressions are caught
by ordinary .test.tsx files that are type-checked during the package
build (tsc --noEmitOnError -p . in
packages/framer-motion/package.json:78) and compiled by ts-jest.
Exemplar: packages/framer-motion/src/motion/__tests__/types.test.tsx
("accepts expected values" pattern).| Purpose | Command (repo root) | Expected |
|---|---|---|
| Build (type-checks all src incl. tests' imports) | yarn build | exit 0 |
| Run the touched test | npx jest --config packages/framer-motion/jest.config.json --testPathPattern="sequence" | all pass |
| Close issue (gated) | gh api -X PATCH repos/motiondivision/motion/issues/2580 -f state=closed -f state_reason=completed | closed |
In scope (only file you may modify):
packages/framer-motion/src/animation/__tests__/animate-sequences.test.tsx
(or the existing sequence test file found via
grep -rln "createAnimationsFromSequence\|animate(\[" packages/framer-motion/src/animation/__tests__ | head -1)
— add ONE small type-exercising test.Out of scope:
packages/motion-dom/src/animation/types.ts — no change needed; the types
are correct.Add the regression test (Step 2 below) FIRST and run yarn build — if the
build's type-check fails on it, the issue is NOT fixed; STOP and report
(this becomes a FIX plan against types.ts).
In the sequence test file (see Scope), add a test that exercises the issue's exact shape — its value is the compile, the runtime assertion is minimal:
test("accepts SVG forced-attr properties in sequence segments (#2580)", () => {
const el = document.createElementNS(
"http://www.w3.org/2000/svg",
"text"
)
// Type regression gate: attrX/attrY/attrScale must be valid segment keys
const animation = animate([
[el, { attrX: 100, attrY: 50, attrScale: 2 }, { duration: 0.01 }],
])
expect(animation).toBeDefined()
animation.stop()
})
Match the file's existing imports (animate is imported from ../../
or framer-motion depending on the file — copy its style).
Verify: yarn build → exit 0 (type-check passed);
npx jest --config packages/framer-motion/jest.config.json --testPathPattern="<that file>" → passes.
Only if the plans/issues/README.md row for this plan is APPROVED:
DOMKeyframesDefinition
includes SVGForcedAttrKeyframesDefinition
(motion-dom/src/animation/types.ts:573-577); regression type test added;
reopen with a minimal .ts snippet + TS version if it still errors.gh api -X PATCH repos/motiondivision/motion/issues/2580 -f state=closed -f state_reason=completedOtherwise mark the row BLOCKED ("verified fixed; awaiting close approval").
yarn build exit 0 with the new test in placegit status)plans/issues/README.md status row updatedattrX — the bug still exists
for the path the executor used (e.g. a different animate overload).
Report the exact compiler error and which import was used.packages/framer-motion/src/animation/__tests__/ contents in the report.DOMKeyframesDefinition is ever split (e.g. SVG types separated for
bundle-size or strictness), this test is the canary for sequence segments.attrX runtime rendering path is covered elsewhere
(buildSVGAttrs → attrs; packages/motion-dom/src/render/svg/utils/build-attrs.ts:83-85);
this plan is only about types.