All notable changes to this project will be documented in this file.
Undocumented APIs may change
The format is based on Keep a Changelog.
partIndexingalso sets--char-count,--word-count,--line-countand--sentence-count(total parts per split type) on the inner[data-splittext-wrapper], inherited by every span for reverse staggers (#355)
@wix/splittext/pluginentry points:splitTextPluginforInteract.use(), andsplitTextStyleforgenerate()(#275)hideUntilReady:splitTextStylehides the container until the runtime split setsdata-splittext-ready(#275)SplitTextPluginConfigexported from the main package types; documents$splitTextfields includingcontainerandhideUntilReady(#329)- README section on validating options and plugin config with
@wix/interact-validate/splittext(#329)
wrapperStyleuses serializableCssStyleRecordvalues instead ofPartial<CSSStyleDeclaration>so configs validate and round-trip as JSON (#329)- Wrapper config types (
WrapperClassConfig,WrapperStyleConfig,WrapperAttrsConfig) exported as type aliases with expanded JSDoc onSplitTextOptions(#329)
- Initial release: lightweight, accessible text splitting for staggered entrance animations (#241)
- Split by chars, words, lines, or sentences with locale-aware
Intl.Segmentersegmentation (#241) - Range API line detection, lazy evaluation, and
revert()to restore the original DOM (#241) - Nested multi-type splits (
lines → sentences → words → chars) withnested: 'flatten'(#241) - CSS stagger hooks (
--char-index,--word-index, etc.) and customizable span wrappers (#241) - React entry point:
useSplitTexthook with automatic cleanup on unmount (#241) - Optional
autoSplitto re-split on resize and font load (#241)
NAMED_EFFECT_PARAMSsemantic check:namedEffectparams are validated against theschemaof the effect registered onInteractunder theirtype—NAMED_EFFECT_INVALID_PARAM(error) for a value that doesn't match its type, enum values, min/max or length/angle format, andNAMED_EFFECT_UNKNOWN_PARAM(warning) for a param the schema doesn't declare (#351)
SCROLL_PRESET_MISSING_RANGE/SCROLL_PRESET_BAD_RANGE(rule categorySCROLL_RANGE), now covered bynamedEffectparams validation.severityOverrideskeyed onSCROLL_RANGEare silently ignored (#351)transitionDelayonpointerMoveeffects; it is reported as an unrecognized key (#354)
- Plugin fields:
$-prefixed keys on interactions and effects are accepted; every other unknown key is still reported asSCHEMA_UNRECOGNIZED_KEYS(#275) @wix/interact-validate/splittextsubpath: zod schemas andvalidateSplitTextOptions()/validateSplitTextPluginConfig()(plusassertValid*helpers) forSplitTextOptionsandSplitTextPluginConfig(#329)- Optional peer dependency on
@wix/splittextfor split-text config types (#329) FUNCTION_OFFSET_EASINGsemantic warning when a sequence'soffsetEasingis a function —generate()cannot compile it to CSS (#289)
HIT_AREA_SHIFT: only warn forpointerMovewith explicithitArea: 'self'; omitted or'root'no longer triggers (default is'root') (#293)
KEYFRAME_PROP_NOT_CAMEL_CASE(rule categoryKEYFRAME_STYLE) is replaced byINVALID_CSS_PROPERTY_NAME(rule categoryCSS_PROPERTY_NAME): both camelCase and kebab-case CSS property names are valid input, so only names that are neither are reported, and the check now coverstransition.styleProperties/transitionPropertiesnames in addition tokeyframeEffectkeyframesseverityOverrideskeyed onKEYFRAME_STYLEare now silently ignored. Rename the key toCSS_PROPERTY_NAMEto keep an override in effect
RECOMMENDED_FILL_BACKWARDSsemantic check nudgingviewEnter+oncekeyframe/named effects without FOUC hiding rules to setfill: 'backwards'or'both'(#277)
- README rule catalog updated for
RECOMMENDED_FILL_BACKWARDS(#277)
- Extended semantic validation derived from
packages/interact/rules/*.md:animationEndgraph warnings, FOUC/same-element retrigger checks, CSS syntax, ignored properties, partial-data guards, and recommended patterns (#252) walkConfig()traversal helper for semantic rule visitors (#252)
- Expanded README with severity model, rule catalog, and integration examples (#252)
- Initial release: static schema, referential, and semantic validation for
InteractConfig, powered by zod (#238) validateInteractConfig(),assertValidInteractConfig(), andInteractValidationError(#238)- Exported zod schemas for host-project composition (
InteractConfigSchema,Interaction,Effect, etc.) (#238) - Structural checks: strict object shapes, enums, numeric bounds, and trigger/effect compatibility (#238)
- Referential and semantic checks: dangling
effectId/sequenceId/conditionsreferences, unused definitions, duplicate keyframe names, and media-query syntax (#238) - Configurable severity via
strict,max, and per-categoryseverityOverrides(#238) - Compile-time type parity guard against
@wix/interactconfig types (#238)
configIndexoption forgenerate()andInteract.create(), for several configs on the same page. Give each config its own index (0,1, …), pass the same one to itsgenerate()andInteract.create(), and insert the configs' CSS in index order (#384)- List custom properties, slots and trigger timeline names are suffixed with the index (
--anm-c1-0,--anm-c1-slot-0,--vw-tmln-c1-0,--trigger-c1-0), so a config's CSS no longer overrides another's - Each config's lists and
:root { timeline-scope }include those of the configs before it, so configs that target the same element play their animations together and their scoped timelines all stay visible - Derived ids of effects and sequences without an
effectId/sequenceIdare suffixed too (eff-c1-0-0,seq-c1-0-0), so their generated@keyframesand state names don't collide between configs
- List custom properties, slots and trigger timeline names are suffixed with the index (
generate()writes the animation list properties of a part animation on the effect's[data-motion-part~="<part>"]element instead of the target, so presets that animate parts (background scroll) work in CSS mode. Overriding a part animation in the cascade only works if the overriding effect sets the same parts again, or if the conditions never match together (#364)
- Bump
@wix/motiondependency to^2.1.18
Interact.getRegisteredEffect()exposes@wix/motion's registered-effect lookup (#351)
- List-item keys whose templated path contains characters other than word characters and
-(e.g.#, as repeaters now use) are matched to their key template and interpolated correctly (#352)
- Unused
transitionDelayfromScrubEffecttypes and docs (#354)
generate()emits a:root { timeline-scope: ... }rule forviewProgresstriggers whose effects target an element other than the source, so a target outside the source's subtree (e.g. a sibling) binds to the source's view timeline instead of staying frozen with anulltimeline (#345)viewProgressandpointerMovehonor an effect'sselectorcondition: no scroll or pointer animation is created for a target that doesn't match it, matchingclick,hover,viewEnter,animationEndand thegenerate()CSS (#344)
- Bump
@wix/motiondependency to^2.1.16
generate()assigns keyframe slots to colliding effects: effects on the same target that would write conflicting animation list entries get their own slot, while effects of the same entry share one and cascade over each other. The runtime resolves an effect's slot from its position in the config, matching the generated CSS (#338)view-timelineis emitted as a list property: eachviewProgressinteraction declares its timeline on its source under its own conditions, so severalviewProgressinteractions can share a source (#338)- Sequence resolution for CSS no longer copies the sequence's conditions onto the config's effects, and skips unresolved sequence references (#338)
viewEnterentrance initial-state rule now resetsclip-path(clip-path: none !important), so entrances whose first keyframe clips the element away (e.g. TiltIn, ShuttersIn, Reveal) no longer hide their own trigger from the IntersectionObserver and never play (#335)
- Runtime interaction IDs and media-query listener keys now incorporate a stable hash of the resolved effect target (selector, list item, etc.) instead of
effectId, so distinct effects on the same element no longer share one controller and cascade each other's updates (#336)
viewEnterwithonce: keep the handler registered until the entrance animation finishes sodestroy()/removecan still cancel in-flight animations; unobserve the source when no handlers remain (#324)
- Optimized styles mitted by
generate()(#320) - Shorter list custom property names (
--anm-0,--anm-cmps-0,--anm-tmln-0,--anm-rng-0,--trns-0; slot variants use-slot-) replace the previous encoded names (#320) animation-timelineandanimation-rangeare no longer written on effect rules when the@propertyinitial values (auto/normal) apply — only set explicitly forviewProgressand similar cases (#320)- Coordinated-list rules are merged into a single rule covering all targets instead of one rule per target (#320)
- Sequence interactions with a single slot write list custom properties directly rather than via an intermediate slot (#320)
instance.destroy({ clearCache?: boolean })— whentrue, removes this instance's controllers fromInteract.controllerCacheon teardown (forwards todisconnect({ removeFromCache })) (#314)
generate()compiles sequence stagger delays intocalc()over--motion-<sequenceId>-indexand--motion-<sequenceId>-lastcustom properties, enabling FOUC-prevented list entrances at build time (#289)- Stable derived IDs when
effectIdorsequenceIdis omitted: effects useeff-<interactionIndex>-<effectIndex>(oreff-<sequenceId>-<effectIndex>inside sequences), sequences useseq-<interactionIndex>-<sequenceIndex>— CSS generation and runtime now agree (#289)
- Sequence stagger timing for CSS animations is driven by custom properties and
calc()delay rather than pre-computed per-effect delays in resolvers (#289) - Sequences whose
offsetEasingis a function are omitted fromgenerate()output (runtime still animates); use a string easing for CSS-pre-rendered stagger (#289) - Interaction rules aligned with runtime:
pointerMovedefaulthitAreais'root';allowA11yTriggersdefaults totrue;useSafeViewEnter, view-progress range definitions,centeredToTarget/transitionDuration/transitionEasingapplicability, andtransitionvstransitionPropertiesmutual exclusion (#293)
- Generic plugin bridge:
Interact.use(name, plugin)registers a plugin, and a$<name>field on an interaction or effect (#275) generate()accepts apluginsoption — a map of plugin name → build-time style generator (#275)
generate(config, options?): the second argument now accepts an options bag —{ useFirstChild?, plugins? }— exported as theGenerateOptions(#275)- CSS property names may be authored in either camelCase or kebab-case in
transition.styleProperties,transitionPropertiesandkeyframeEffect.keyframes; state-effect properties are normalized to kebab-case for the generated CSS (state rules and thetransition:shorthand) and keyframes to camelCase for WAAPI (#281)
- camelCase property names in
transition.styleProperties/transitionPropertiesare now normalized to kebab-case (#281) - CSS custom properties in keyframes (e.g.
--fooBar) are no longer lower-cased when emitted into@keyframes(#281) - Vendor-prefixed keyframe properties (e.g.
webkitTextStroke) now emit a valid CSS property name (-webkit-text-stroke) (#281)
- Entrance FOUC prevention:
generate()initial rules now emit!importanton transform neutralization declarations so they override inline styles until the animation starts (#277)
viewEnterrules and docs recommendfill: 'backwards'(or'both') for entrance animations; CSS rule declarations support an optionalimportantflag (#277)
- Sequence triggers now resolve the interaction's
sourceselector (including list items) and mark interactions as added only after elements resolve, so unresolved sources can be retried on later passes (#272)
- Interaction rules updated to recommend build-time CSS generation via
generate()forviewEnter,viewProgress,hover, andclickintegrations (#262)
- Coding agents instructions in package
README.md(#257)
- Improved interactor usage documentation in
README.md(#258) - Updated
rules/validate.mdfor extended@wix/interact-validatesemantic checks (#252) - React and custom-elements integration docs refreshed for interactor skill workflows (#242)
- Removed React
initialprop anddata-interact-initialFOUC marker; entrance FOUC prevention now relies solely on injectinggenerate()CSS (#247)
- Single-keyframe effects with an explicit
offset(e.g.0) no longer have their offset overwritten to1ininterpolateKeyframesOffsets(#247)
- Agent rules (
rules/validate.md) and docs for validating configs with@wix/interact-validate(#238) - Export
SequenceOptionsConfigfrom public types (#238)
Condition.predicateis now required (#238)- Removed
pageVisibletrigger; useviewEnterinstead (#238) - Corrected add/remove interaction rules in
full-lean.mdandintegration.md(#244)
- Entrance SSR: split FOUC-prevention CSS into separate rules for
:not([data-interact-enter])(initial state) and:not([data-interact-enter="done"])(animation), so hydration can mark entrance complete without flash (#243)
- Revamp package
README.mdwith expanded overview,generate()documentation, framework integration guides, and examples (#214) - README follow-up: add
llmsandllmsFullfields topackage.json, AI discovery section, and corrected documentation and dependency links (#216)
- FOUC-prevention CSS: apply
:not([data-interact-enter])on the animated child selector instead of the source element, so initial-state hiding targets the correct element when effects useselector(#229) animationEndtrigger: resolve and match only the source animation identified byeffectId(viaanimationNameanddetail.effectId), so unrelatedanimationendevents on the source no longer fire chained effects (#227)
- Rewrite
generate()to produce complete CSS from anInteractConfig:@keyframes, animation and transition custom properties,view-timelinedeclarations, state-selector rules, coordinated-list aggregation, and FOUC-prevention initial rules (#7) - Ship
llms.txtin the published package; addscripts/generate-llms.mjsplus CI workflows to generate and deploy it (#212, #215) - Monorepo root
README.mdwith project overview and integration guidance (#213) - Interactive examples website (
apps/website) with landing page and example gallery (#199) - Extensive tests for CSS generation, resolvers, and utilities (#7)
InteractConfig.effectsis now optional (#7)- Docs and interaction rules updated for the new
generate()implementation, FOUC prevention, and scroll-driven pre-rendering (#211) viewProgresshandler usesgetAnimation()and skips WAAPI playback when the animation group is CSS-based (isCSS) (#7)- Refactored transition CSS helpers and shared selector/property utilities (#7)
- Unused public type exports:
EventTriggerKind,EventTriggerConfigToggle,EventTriggerConfigEnterLeave,EventTriggerConfig,AnimationOptions,SequenceOptionsConfig(#205)
- Attach adopted constructed stylesheets to the element's root (
documentorShadowRoot) so dynamically injected CSS applies when Interact runs inside shadow DOM (#173) - Register sequence effect selectors on the source interaction so sequence steps resolve selectors when the animated target differs from the source element (#173)
- Allow React 19 in
peerDependenciesforreactandreact-dom(#194) - Revise package description and expand npm keywords
- Added a Playground app and publish it under
/playground.
- Console warnings when
Interact.getInstance()orInteract.getController()cannot resolve a key (#190)
- React integration rules: document wrapping
Interact.create()inuseEffectwith cleanup callingdestroy()(#190)
- Replace
typeandmethodinInteraction.paramswithtriggerTypeandstateActiononTimeEffectandStateEffect(#180) - Split public types into focused modules for clearer API docs and maintenance (#181)
- Completely revamped and refreshed interaction rules (#159)
- Fix typo:
useCutsomElement→useCustomElementin types/options (#172)
- Bump
@wix/motiondependency to^2.1.3(#169)
- Add support to
onAbortto fire correctly when an animation is aborted mid-play (#163)
- Fix
viewEnterinset value to be negated when applied asrootMargin(#166) - Add default
threshold: 0.2forviewEnterintersection observer (#166)
- Add
build:landingscript and improveviewEnterexample (#158) - Bump
@wix/motiondependency to^2.1.0
- Fix leave event listeners are not added when using transition effects with
hoverorinteresttriggers without explicitparams: { method: 'toggle' }
- Sequences: coordinated multi-element animation sequences with staggered delays (#133)
- New
SequenceConfigandSequenceConfigReftypes for declarative sequence configuration (#133) - New
sequencesproperty on interactions and top-level config for reusable sequence definitions (#133) - Dynamic add/remove of sequence groups for list item support (#133)
- Sequence documentation, guides, and demos (#133)
- Rules rewrite for all interaction types (#135)
- Bump
@wix/motiondependency to^2.1.0
- Fix interpolated keys multi-trigger bug (#139)
- Refactor event triggers: more generic eventTriggers, allow adding triggers more easily (#129)
- Move to wix org on GH (#126)
- Fix applying effects when interaction conditions do not match (#123)
- Fix homepage, docs, and rules (#122)
- Move to wix org on GitHub (#126)
- Initial release.
- Named effects can declare the
partsthey animate.getElementCSSAnimation()andgetElementAnimation()then read the animations from those[data-motion-part~="<part>"]elements instead of the target (#364)
getCSSAnimation()returns the animation'spartinstead of atargetselector (#364)
getEffectsData()no longer normalizes preset keyframes beforedom.measure()runs, so lazy keyframes/ranges that depend on measured layout are read at apply time — fixing zero Cross loop offsets and background-scroll ranges that ignored component height (#347)
- Unused
transitionDelayfrom scrub animation data types and docs (#354)
- Export
getRegisteredEffect(); it accepts an optionalwarnargument (defaulttrue) to skip the missing-preset warning (#338) - Optional
suffixonTimeAnimationOptionsand scrub animation data (#338)
- Republish aligning monorepo dependents on
@wix/motion@2.1.15; no API changes since 2.1.9 (#327)
toCSSPropertyName(),toWAAPIPropertyName()andnormalizeKeyframes()utilities for converting CSS property names between their CSS and WAAPI forms (#281)getJsEasingInCSS(),jsEasingsInCSS, andcubicBezierCalc()for expressing offset easings as CSScalc()math (#289)Sequence.sequenceIdoption; CSS-based sequences set--motion-<sequenceId>-indexand--motion-<sequenceId>-laston targets instead of per-animation delay offsets (#289)getCSSAnimation()accepts optionalsequenceOptionsto emit stagger delays ascalc()(#289)- Exported
cubicBezierEasing()from utils (#289)
- Keyframe property names may be authored in either camelCase or kebab-case and are normalized to WAAPI's camelCase on every animation path —
keyframeEffect, presets, and effects registered viaregisterEffects()(#281) Sequence.applyOffsets(): CSS animation groups with asequenceIduse custom-property-driven delays via generated CSS rather thanupdateTiming({ delay })(#289)
getWebAnimation()accepts SVG elements (and anyElement) as keyframe targets, not onlyHTMLElement(#280)
getCSSAnimation()delay serialization: use0mswhendelayis0instead of previously defaulting to1ms(#277)
AnimationGroup.hasAnimationName()andAnimationGroup.hasAnimationId()for checking which animation finished (#227)
- Revamp package
README.mdwith expanded API reference, usage examples, scroll/pointer/sequence sections, AI/llms.txtpointers, and corrected links (#216) - Dispatched
animationendis now aCustomEventwithdetail.effectIdfor effect-specific matching (#227) AnimationGroup.playStatereturnsrunningwhen any child animation is running (#227)
getEffectsData()accepts an optionalforCSSflag so CSS generation always emitsduration: autofor view-progress triggers without requiringwindow.ViewTimelineat build time (#7)
- Revise package description and expand npm keywords
- Implement
AnimationGroup.getProgress()correctly (#179)
- Bump package version for publish (#168)
- Add
onAbortmethod toAnimationGroupfor invoking callback when animation is aborted (#163) - Add Playwright e2e test suite covering animation groups, effects, pointer, and scroll animations (#131)
- Fix
Sequence.applyOffsets()crash when called with empty animation groups (#152)
Sequenceclass: coordinated animation timeline with stagger offsets, add/remove groups (#133)getSequence()function to createSequenceinstances fromAnimationGroupArgs(#133)createAnimationGroups()function for buildingAnimationGrouparrays (#133)AnimationGroup.getTimingOptions()method for extracting timing data (#133)- New types:
SequenceOptions,AnimationGroupArgs,IndexedGroup(#133) getJsEasing()now supports parsing CSScubic-bezier()andlinear()easing strings (#133)
- Rename
getCssUnitsparameter fromtypetounit(#122) - RangeOffset API: use
unitinstead oftypefor offset specification (#122)
- Documentation cleanup and consolidation (#122)
- Move to wix org on GitHub (#126)
- Initial release.
- Background scroll presets export the
partsthey animate (#364)
- Background scroll part names:
BG_LAYERis nowMEDIA_CLIP,BG_MEDIAis nowMEDIA_WRAPPER, andBG_IMGis nowMEDIA. Elements must use the newdata-motion-partvalues (#364) - Bump
@wix/motiondependency to^2.1.18
- Background scroll presets declare the custom properties their keyframes use, so they work in CSS mode (#364)
- Every preset honors the
suffixoption: it is appended to the preset's animation names and to the CSS custom properties it declares (and theirvar()references), so the same preset in different keyframe slots of one element doesn't override the other's parameters (#353)
- Bump
@wix/motiondependency to^2.1.15(#327)
@wix/motion-presets/browserentry point: self-contained browser bundle (dist/browser/motion-presets.js) with@wix/motioninlined for dynamic import without an import map (#316)
- Entrance presets default to
fill: 'backwards'viagetEntranceFill()unless overridden (#277)
- Bump
@wix/motiondependency to^2.1.6(#223)
- Revise package description and expand npm keywords
- Add
iterationDelayto ongoing presets (replaces formerdelayusage) (#178)
- Fix
fadeInfor ShuttersIn and GlideIn presets (#177)
- Initial release.