Skip to content

Add reducedMotionHandling to @wix/interact - #400

Merged
ydaniv merged 7 commits into
masterfrom
reduced-motion-plan-and-design
Nov 4, 2026
Merged

ydaniv merged 7 commits into
masterfrom
reduced-motion-plan-and-design

Conversation

@ameerf-wix

@ameerf-wix ameerf-wix commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Implements the design in docs/reduced-motion-design.md.

  • reducedMotionPolicy: 'collapse' (default) | 'ignore' | 'cancel' | effectId. It can be set on interactions, sequences and effects, and per instance; the most specific wins. The instance value isn't a config field: Interact.setup() sets it for every instance, Interact.create(config, options) overrides it for one, and generate() takes it as an option.
  • collapse plays one 0ms iteration that keeps the delay and ends where the effect would (fractional iterations and backwards alternate iterations included). Effects with no end state (looping, viewProgress, pointerMove) are cancelled. A sequence's stagger collapses too, unless its handling is 'ignore'.
  • Each effect yields variants under exclusive prefers-reduced-motion media: generate() emits them, and the runtime picks the matching one. No effects are added to the config, so ids, slots and list entries are unchanged.
  • forceReducedMotion (Interact.setup(), Interact.create(), generate()) applies the reduced outcome instead of passing reducedMotion to motion.
  • @wix/interact-validate: schema for the field, plus reference, kind-compatibility and semantic checks. They run inside the existing config walks.

Breaking: under OS reduce, effects now collapse by default. Opt out with Interact.setup({ reducedMotionPolicy: 'ignore' }). With the default, forceReducedMotion keeps its old behavior, except that finite multi-iteration animations collapse to their end state instead of being dropped.

Verified with unit tests, and in Chromium / Firefox / WebKit comparing WAAPI-only against generate() CSS under reduce / no-preference: entrances, sequence stagger, variation overrides, collapsed iteration end states, and live media toggles.

🤖 Generated with Claude Code

A cascading `reducedMotionHandling` field (`ignore` | `cancel` | `collapse` |
effectId) on the config, interactions, sequences and effects. Each effect
position yields variants under exclusive reserved prefers-reduced-motion media,
which generate() emits and the runtime picks from, so the WAAPI and CSS paths
match without adding effects to the config. `Interact.forceReducedMotion` now
applies the reduced outcome, with a matching generate() option.

Validation, docs and the design doc (docs/reduced-motion-design.md) included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Generated llms.txt preview

llms.txt
# @wix/interact

> Declarative, configuration-driven interaction library — web-native, AI-ready, and framework-agnostic.

- Install: `npm install @wix/interact @wix/motion-presets`
- Three entry points: vanilla JS (`@wix/interact`), React (`@wix/interact/react`), Web Components (`@wix/interact/web`)
- Five trigger types: hover, click, viewEnter, viewProgress, pointerMove
- Effects via named presets (`@wix/motion-presets`), keyframes, CSS transitions, or custom JS callbacks
- Configs are JSON-serializable -- designed for LLM generation

## Docs

- [Full Reference](https://wix.github.io/interact/rules/full-lean.md): Declarative configuration-driven interaction library. Binds animations to triggers via JSON config. (817 lines)
- [Integration Guide](https://wix.github.io/interact/rules/integration.md): Rules for integrating `@wix/interact` into a webpage — binding animations and effects to user-driven triggers via declarative configuration. (368 lines)
- [Validation Guide](https://wix.github.io/interact/rules/validate.md): Rules for using `@wix/interact-validate` — validate an `InteractConfig` before it reaches the runtime. (324 lines)

## Optional

- [Click Trigger Rules for @wix/interact](https://wix.github.io/interact/rules/click.md): This document contains rules for generating click-triggered interactions in `@wix/interact`. (197 lines)
- [Hover Trigger Rules for @wix/interact](https://wix.github.io/interact/rules/hover.md): This document contains rules for generating hover-triggered interactions in `@wix/interact`. (199 lines)
- [PointerMove Trigger Rules for @wix/interact](https://wix.github.io/interact/rules/pointermove.md): These rules help generate pointer-driven interactions using `@wix/interact`. (271 lines)
- [ViewEnter Trigger Rules for @wix/interact](https://wix.github.io/interact/rules/viewenter.md): This document contains rules for generating interactions that respond to elements entering the viewport using the `@wix/interact`. (232 lines)
- [ViewProgress Trigger Rules for @wix/interact](https://wix.github.io/interact/rules/viewprogress.md): These rules help generate scroll-driven interactions using `@wix/interact`. (233 lines)
- [@wix/interact Plugin Rules](https://wix.github.io/interact/rules/plugins.md): Rules for extending `@wix/interact` with external plugins via `Interact.use()` and `$`-prefixed config fields. (140 lines)
- [All rules in one file](https://wix.github.io/interact/llms-full.txt): Complete concatenation (2781 lines)
llms-full.txt header
# @wix/interact v2.7.0 -- AI Rules Reference
# https://wix.github.io/interact/llms.txt
# 9 files, 2781 lines

Download full files from workflow artifacts, or run node scripts/generate-llms.mjs locally.

Comment thread docs/reduced-motion-design.md Resolved
Comment thread docs/reduced-motion-design.md Resolved
Comment thread docs/reduced-motion-design.md Resolved
Comment thread packages/interact/src/core/add.ts Resolved
Comment thread packages/interact/src/core/css.ts Resolved
Comment thread packages/interact/src/core/css.ts Resolved
ameerf-wix and others added 3 commits November 4, 2026 15:24
…ation

- reducedMotionHandling defaults to 'collapse'; collapse also takes finite
  iterations to one, and a sequence's stagger collapses unless it's ignored
- forceReducedMotion can be set per instance via Interact.create()
- handling is resolved from values, not the objects holding them; the
  time/scrub kind uses effectToAnimationOptions' discriminator
- replacement body fields are typed against the effect types; runtime
  fallback warnings are dropped (the validator reports them)
- CSS variants fall back only the entries assigned before their effect; an
  instant entrance is detected from its own duration
- keyframe naming stays where it was in resolveEffectForCSS
- validate: reduced-motion checks run inside the existing walks, replacement
  kinds come from the effect schemas, sequence definitions are reported per
  reference instead of deduplicated, shared helpers and modes are reused

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nal iterations

- reducedMotionHandling is no longer a config field: Interact.setup() sets
  the default for every instance, Interact.create() options override it per
  instance, and generate() takes it as an option defaulting to setup()'s
- forceReducedMotion is set through Interact.setup() too
- collapse keeps the fraction of fractional iterations and flips `reversed`
  when the last alternate iteration runs backwards, so the collapsed effect
  ends where the full one does
- the validator rejects the field on the config root and assumes the default
  instance handling

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-and-design

# Conflicts:
#	CHANGELOG.md
#	packages/interact/src/core/Interact.ts
#	packages/interact/src/core/add.ts
Comment thread packages/interact-validate/src/types.ts Resolved
Comment thread packages/interact/src/core/resolvers.ts Resolved
Comment thread packages/interact/src/core/resolvers.ts Resolved
ameerf-wix and others added 2 commits November 4, 2026 17:25
- reducedMotionHandling / ReducedMotionHandling are now reducedMotionPolicy /
  ReducedMotionPolicy everywhere, docs included
- the validator's reduced-motion checks run last in each walk batch
- BODY_FIELDS is a plain array again
- the resolver's option and FullEffect types live in types/css.ts
- keyframe naming is back before the CSS-rules check, with resolveBody at
  module level

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ydaniv
ydaniv merged commit 0496338 into master Nov 4, 2026
2 checks passed
@ydaniv
ydaniv deleted the reduced-motion-plan-and-design branch November 4, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants