@wix/interact 2.1.4 → 2.2.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.
Files changed (83) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/react.js +1 -1
  3. package/dist/cjs/web.js +1 -1
  4. package/dist/cjs/web.js.map +1 -1
  5. package/dist/es/index.js +1 -1
  6. package/dist/es/react.js +2 -2
  7. package/dist/es/web.js +15 -15
  8. package/dist/es/web.js.map +1 -1
  9. package/dist/{index-DHqlFmW8.mjs → index-ByLXasWO.mjs} +491 -485
  10. package/dist/index-ByLXasWO.mjs.map +1 -0
  11. package/dist/index-CzRuJxn8.js +18 -0
  12. package/dist/index-CzRuJxn8.js.map +1 -0
  13. package/dist/tsconfig.build.tsbuildinfo +1 -1
  14. package/dist/types/core/Interact.d.ts +2 -2
  15. package/dist/types/core/InteractionController.d.ts +2 -2
  16. package/dist/types/core/InteractionController.d.ts.map +1 -1
  17. package/dist/types/core/add.d.ts.map +1 -1
  18. package/dist/types/core/css.d.ts.map +1 -1
  19. package/dist/types/handlers/effectHandlers.d.ts +4 -4
  20. package/dist/types/handlers/effectHandlers.d.ts.map +1 -1
  21. package/dist/types/handlers/eventTrigger.d.ts +2 -2
  22. package/dist/types/handlers/eventTrigger.d.ts.map +1 -1
  23. package/dist/types/handlers/index.d.ts.map +1 -1
  24. package/dist/types/handlers/viewEnter.d.ts.map +1 -1
  25. package/dist/types/index.d.ts +1 -1
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/react/index.d.ts +1 -1
  28. package/dist/types/react/index.d.ts.map +1 -1
  29. package/dist/types/types/config.d.ts +47 -0
  30. package/dist/types/types/config.d.ts.map +1 -0
  31. package/dist/types/types/controller.d.ts +34 -0
  32. package/dist/types/types/controller.d.ts.map +1 -0
  33. package/dist/types/types/effects.d.ts +75 -0
  34. package/dist/types/types/effects.d.ts.map +1 -0
  35. package/dist/types/types/external.d.ts +6 -0
  36. package/dist/types/types/external.d.ts.map +1 -0
  37. package/dist/types/types/global.d.ts +11 -0
  38. package/dist/types/types/global.d.ts.map +1 -0
  39. package/dist/types/types/handlers.d.ts +41 -0
  40. package/dist/types/types/handlers.d.ts.map +1 -0
  41. package/dist/types/types/index.d.ts +8 -0
  42. package/dist/types/types/index.d.ts.map +1 -0
  43. package/dist/types/types/internal.d.ts +36 -0
  44. package/dist/types/types/internal.d.ts.map +1 -0
  45. package/dist/types/types/triggers.d.ts +28 -0
  46. package/dist/types/types/triggers.d.ts.map +1 -0
  47. package/dist/types/web/InteractElement.d.ts +2 -2
  48. package/dist/types/web/InteractElement.d.ts.map +1 -1
  49. package/dist/types/web/index.d.ts +1 -1
  50. package/dist/types/web/index.d.ts.map +1 -1
  51. package/docs/api/README.md +2 -3
  52. package/docs/api/functions.md +4 -4
  53. package/docs/api/interact-class.md +2 -3
  54. package/docs/api/interact-element.md +2 -2
  55. package/docs/api/interaction-controller.md +4 -4
  56. package/docs/api/types.md +38 -69
  57. package/docs/examples/README.md +1 -1
  58. package/docs/examples/click-interactions.md +0 -7
  59. package/docs/examples/entrance-animations.md +28 -27
  60. package/docs/examples/list-patterns.md +17 -16
  61. package/docs/guides/conditions-and-media-queries.md +2 -3
  62. package/docs/guides/configuration-structure.md +5 -7
  63. package/docs/guides/effects-and-animations.md +2 -4
  64. package/docs/guides/getting-started.md +0 -1
  65. package/docs/guides/lists-and-dynamic-content.md +10 -9
  66. package/docs/guides/sequences.md +3 -4
  67. package/docs/guides/state-management.md +0 -2
  68. package/docs/guides/understanding-triggers.md +9 -13
  69. package/package.json +2 -2
  70. package/rules/click.md +96 -560
  71. package/rules/full-lean.md +536 -360
  72. package/rules/hover.md +107 -530
  73. package/rules/integration.md +212 -261
  74. package/rules/pointermove.md +154 -1407
  75. package/rules/viewenter.md +128 -863
  76. package/rules/viewprogress.md +88 -322
  77. package/dist/index-DHqlFmW8.mjs.map +0 -1
  78. package/dist/index-DYEvpIGz.js +0 -18
  79. package/dist/index-DYEvpIGz.js.map +0 -1
  80. package/dist/types/types.d.ts +0 -256
  81. package/dist/types/types.d.ts.map +0 -1
  82. package/rules/MASTER-CLEANUP-PLAN.md +0 -286
  83. package/rules/scroll-list.md +0 -748
package/rules/hover.md CHANGED
@@ -1,614 +1,191 @@
1
1
  # Hover Trigger Rules for @wix/interact
2
2
 
3
- This document contains rules for generating hover trigger interactions in `@wix/interact`. These rules cover all hover behavior patterns and common use cases.
3
+ This document contains rules for generating hover-triggered interactions in `@wix/interact`.
4
4
 
5
- ## Rule 1: Basic Hover Effect Configuration
5
+ **CRITICAL Accessible hover**: Use `trigger: 'interest'` instead of `trigger: 'hover'` to also respond to keyboard focus.
6
6
 
7
- **Purpose**: Generate basic hover interactions with enter/leave animations
7
+ - **CRITICAL**: MUST AVOID using the same element as both trigger source and effect target with effects that change size or position (e.g. `transform: translate(…)`, `scale(…)`). The transform shifts the hit area, causing jittery re-entry cycles. Instead, use `selector` to target a child element for the animation.
8
8
 
9
- **Pattern**:
9
+ ## Table of Contents
10
10
 
11
- ```typescript
12
- {
13
- key: '[SOURCE_KEY]',
14
- trigger: 'hover',
15
- effects: [
16
- {
17
- key: '[TARGET_KEY]',
18
- [EFFECT_TYPE]: [EFFECT_DEFINITION],
19
- fill: 'both',
20
- duration: [DURATION_MS],
21
- easing: '[EASING_FUNCTION]'
22
- }
23
- ]
24
- }
25
- ```
26
-
27
- **Variables**:
28
-
29
- - `[SOURCE_KEY]`: Unique identifier for hoverable element. Should equal the value of the `data-interact-key` attribute on the wrapping `<interact-element>`.
30
- - `[TARGET_KEY]`: Unique identifier for animated element (can be same as `[SOURCE_KEY]` for self-targeting, or different for cross-targeting).
31
- - `[EFFECT_TYPE]`: Either `namedEffect` or `keyframeEffect`
32
- - `[EFFECT_DEFINITION]`: Named effect object (e.g., { type: 'SlideIn', ...params }, { type: 'FadeIn', ...params }) or keyframe object (e.g., { name: 'custom-fade', keyframes: [{ opacity: 0 }, { opacity: 1 }] }, { name: 'custom-slide', keyframes: [{ transform: 'translateX(-100%)' }, { transform: 'translateX(0)' }] })
33
- - `[DURATION_MS]`: Animation duration in milliseconds (typically 200-500ms for micro-interactions)
34
- - `[EASING_FUNCTION]`: Timing function ('ease-out', 'ease-in-out', or cubic-bezier)
35
- - `[UNIQUE_EFFECT_ID]`: Optional unique identifier for animation chaining
11
+ - [Rule 1: keyframeEffect / namedEffect (TimeEffect)](#rule-1-keyframeeffect--namedeffect-timeeffect)
12
+ - [Rule 2: transition / transitionProperties (StateEffect)](#rule-2-transition--transitionproperties-stateeffect)
13
+ - [Rule 3: customEffect (TimeEffect)](#rule-3-customeffect-timeeffect)
14
+ - [Rule 4: Sequences](#rule-4-sequences)
36
15
 
37
- **Default Values**:
38
-
39
- - `DURATION_MS`: 300 (for micro-interactions)
40
- - `EASING_FUNCTION`: 'ease-out' (for smooth feel)
41
- - `[TARGET_KEY]`: Same as `[SOURCE_KEY]` for self-targeting
42
-
43
- **Common Use Cases**:
44
-
45
- - Button hover states
46
- - Card lift effects
47
- - Image zoom effects
48
- - Color/opacity changes
49
-
50
- **Example Generations**:
51
-
52
- ```typescript
53
- // Button hover
54
- {
55
- key: 'primary-button',
56
- trigger: 'hover',
57
- effects: [
58
- {
59
- key: 'primary-button',
60
- keyframeEffect: {
61
- name: 'button-shadow',
62
- keyframes: [
63
- { transform: 'scale(1)', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
64
- { transform: 'scale(1.05)', boxShadow: '0 8px 16px rgba(0,0,0,0.15)' }
65
- ]
66
- },
67
- fill: 'both',
68
- duration: 200,
69
- easing: 'ease-out'
70
- }
71
- ]
72
- }
16
+ ---
73
17
 
74
- // Image hover zoom
75
- {
76
- key: 'product-image',
77
- trigger: 'hover',
78
- effects: [
79
- {
80
- key: 'product-image-media',
81
- keyframeEffect: {
82
- name: 'image-scale',
83
- keyframes: [
84
- { transform: 'scale(1)' },
85
- { transform: 'scale(1.1)' }
86
- ]
87
- },
88
- fill: 'both',
89
- duration: 400,
90
- easing: 'ease-out'
91
- }
92
- ]
93
- }
94
- ```
18
+ ## Rule 1: keyframeEffect / namedEffect (TimeEffect)
95
19
 
96
- ## Rule 2: Hover Alternate Animations (namedEffect / keyframeEffect)
20
+ Use `keyframeEffect` or `namedEffect` when the hover should play an animation (CSS or WAAPI). Set `triggerType` on each effect to control playback behavior.
97
21
 
98
- **Purpose**: Hover interactions that play forward on mouse enter and reverse on mouse leave (`type: 'alternate'`).
22
+ **CRITICAL:** Always include `fill: 'both'` for `triggerType: 'alternate'`, `'repeat'` — keeps the effect applied while hovering and prevents garbage-collection. For `triggerType: 'once'` use `fill: 'backwards'`.
99
23
 
100
- **Pattern**:
24
+ **Multiple effects:** The `effects` array can contain multiple effects — all share the same hover trigger and fire together. Use this to animate different targets from a single hover event.
101
25
 
102
26
  ```typescript
103
27
  {
104
28
  key: '[SOURCE_KEY]',
105
29
  trigger: 'hover',
106
- params: {
107
- type: 'alternate'
108
- },
109
30
  effects: [
110
31
  {
111
32
  key: '[TARGET_KEY]',
112
- // Use namedEffect OR keyframeEffect:
113
- namedEffect: { type: '[NAMED_EFFECT_TYPE]' },
114
- // keyframeEffect: { name: '[EFFECT_NAME]', keyframes: [{ ... }, { ... }] },
115
- fill: 'both',
116
- reversed: [REVERSED_BOOL],
117
- duration: [DURATION_MS],
118
- easing: '[EASING_FUNCTION]'
119
- }
120
- ]
121
- }
122
- ```
123
-
124
- **Variables**:
125
-
126
- - `[REVERSED_BOOL]`: Optional. `true` to reverse the enter direction (mouse enter plays backwards, leave plays forwards).
127
- - `[NAMED_EFFECT_TYPE]`: Pre-built effect from `@wix/motion-presets`. Available hover presets:
128
- - Size: `ExpandIn`, `Pulse`, `GrowIn`
129
- - Fade/Blur: `FadeIn`, `Flash`, `BlurIn`
130
- - Translate: `SlideIn`, `GlideIn`, `FloatIn`, `BounceIn`, `GlitchIn`
131
- - Rotate: `SpinIn`, `TiltIn`, `ArcIn`, `TurnIn`, `FlipIn`, `Spin`, `Swing`
132
- - Attention: `Bounce`, `DropIn`, `Rubber`, `Jello`, `Cross`, `Wiggle`, `Poke`
133
- - Other variables same as Rule 1
134
-
135
- **Important**: Spatial effects (translation, rotation) that change the hit-area considerably should use different source and target keys to avoid flickering on enter/leave.
136
-
137
- **Default Values**:
138
-
139
- - `DURATION_MS`: 250–300
140
- - `EASING_FUNCTION`: 'ease-out'
141
-
142
- **Example — namedEffect (card scale)**:
143
-
144
- ```typescript
145
- {
146
- key: 'feature-card',
147
- trigger: 'hover',
148
- params: { type: 'alternate' },
149
- effects: [
150
- {
151
- key: 'feature-card',
152
- namedEffect: { type: 'Pulse' },
153
- fill: 'both',
154
- duration: 250,
155
- easing: 'ease-out'
156
- }
157
- ]
158
- }
159
- ```
160
-
161
- **Example — keyframeEffect (card lift)**:
33
+ triggerType: '[TRIGGER_TYPE]',
162
34
 
163
- ```typescript
164
- {
165
- key: 'portfolio-item',
166
- trigger: 'hover',
167
- params: { type: 'alternate' },
168
- effects: [
169
- {
170
- key: 'portfolio-item',
35
+ // --- pick ONE of the two effect types ---
171
36
  keyframeEffect: {
172
- name: 'portfolio-lift',
173
- keyframes: [
174
- { transform: 'translateY(0)', boxShadow: '0 4px 6px rgba(0,0,0,0.1)' },
175
- { transform: 'translateY(-8px)', boxShadow: '0 20px 25px rgba(0,0,0,0.15)' }
176
- ]
37
+ name: '[EFFECT_NAME]',
38
+ keyframes: [KEYFRAMES],
177
39
  },
178
- fill: 'both',
179
- duration: 300,
180
- easing: 'ease-out'
181
- }
182
- ]
183
- }
184
- ```
185
-
186
- ## Rule 3: Hover Interactions with Repeat Pattern
40
+ // OR
41
+ namedEffect: [NAMED_EFFECT_DEFINITION],
187
42
 
188
- **Purpose**: Generate hover interactions that restart animation each time mouse enters
189
-
190
- **Pattern**:
191
-
192
- ```typescript
193
- {
194
- key: '[SOURCE_KEY]',
195
- trigger: 'hover',
196
- params: {
197
- type: 'repeat'
198
- },
199
- effects: [
200
- {
201
- key: '[TARGET_KEY]',
202
- [EFFECT_TYPE]: [EFFECT_DEFINITION],
43
+ fill: '[FILL_MODE]',
203
44
  duration: [DURATION_MS],
204
- easing: '[EASING_FUNCTION]'
205
- }
45
+ easing: '[EASING_FUNCTION]',
46
+ delay: [DELAY_MS],
47
+ iterations: [ITERATIONS],
48
+ alternate: [ALTERNATE_BOOL]
49
+ },
50
+ // additional effects targeting other elements can be added here
206
51
  ]
207
52
  }
208
53
  ```
209
54
 
210
- **Variables**:
211
-
212
- - Same as Rule 1
213
-
214
- **Use Cases for Repeat Pattern**:
55
+ ### Variables
215
56
 
216
- - Attention-grabbing animations
217
- - Pulse effects
218
- - Shake/wiggle animations
219
- - Bounce effects
57
+ - `[SOURCE_KEY]` — identifier matching the element's key (`data-interact-key` for web, `interactKey` for React). The element that listens for hover.
58
+ - `[TARGET_KEY]` — identifier matching the element's key on the element that animates. Use a different key from `[SOURCE_KEY]` when source and target must be separated (see hit-area shift above).
59
+ - `[TRIGGER_TYPE]` — `triggerType` on the effect. One of:
60
+ - `'alternate'` — plays forward on enter, reverses on leave. Default. Most common for hover.
61
+ - `'repeat'` — restarts the animation from the beginning on each enter. On leave, jumps to the beginning and pauses.
62
+ - `'once'` — plays once on the first enter and never again.
63
+ - `'state'` — resumes on enter, pauses on leave. Useful for continuous loops (`iterations: Infinity`).
64
+ - `[KEYFRAMES]` — array of keyframe objects (e.g. `[{ opacity: 0 }, { opacity: 1 }]`). Property names in camelCase.
65
+ - `[EFFECT_NAME]` — unique string identifier for a `keyframeEffect`.
66
+ - `[NAMED_EFFECT_DEFINITION]` — object with properties of pre-built effect from `@wix/motion-presets`. Refer to motion-presets rules for available presets and their options.
67
+ - `[DURATION_MS]` — animation duration in milliseconds.
68
+ - `[EASING_FUNCTION]` — CSS easing string (e.g. `'ease-out'`, `'ease-in-out'`, `'cubic-bezier(0.4, 0, 0.2, 1)'`), or named easing from `@wix/motion`.
69
+ - `[DELAY_MS]` — optional delay before the effect starts, in milliseconds.
70
+ - `[ITERATIONS]` — optional. Number of iterations, or `Infinity` for continuous loops. Primarily useful with `triggerType: 'state'`.
71
+ - `[ALTERNATE_BOOL]` — optional. `true` to alternate direction on every other iteration (within a single playback).
72
+ - `[FILL_MODE]` — usually `'both'`. Keeps the final state applied while hovering, and prevents garbage-collection of animation when finished.
220
73
 
221
- **Default Values**:
222
-
223
- - `type`: 'repeat'
224
- - `DURATION_MS`: 600 (longer for noticeable repeat)
225
- - `EASING_FUNCTION`: 'ease-in-out'
226
-
227
- **Example Generations**:
228
-
229
- ```typescript
230
- // Button pulse effect
231
- {
232
- key: 'cta-button',
233
- trigger: 'hover',
234
- params: {
235
- type: 'repeat'
236
- },
237
- effects: [
238
- {
239
- key: 'cta-button',
240
- namedEffect: {
241
- type: 'Breath'
242
- },
243
- duration: 600,
244
- easing: 'ease-in-out'
245
- }
246
- ]
247
- }
248
-
249
- // Icon shake effect
250
- {
251
- key: 'notification-bell',
252
- trigger: 'hover',
253
- params: {
254
- type: 'repeat'
255
- },
256
- effects: [
257
- {
258
- key: 'notification-bell',
259
- keyframeEffect: {
260
- name: 'shake',
261
- keyframes: [
262
- { transform: 'rotate(0deg)' },
263
- { transform: 'rotate(15deg)' },
264
- { transform: 'rotate(-15deg)' },
265
- { transform: 'rotate(0deg)' }
266
- ]
267
- },
268
- duration: 500,
269
- easing: 'ease-in-out'
270
- }
271
- ]
272
- }
273
- ```
74
+ ---
274
75
 
275
- ## Rule 4: Hover Interactions with Play/Pause Pattern
76
+ ## Rule 2: transition / transitionProperties (StateEffect)
276
77
 
277
- **Purpose**: Generate hover interactions that pause/resume on hover (state-based control)
78
+ Use `transition` or `transitionProperties` when the hover should toggle styles via DOM attribute change and CSS transitions rather than keyframe animations. Set `stateAction` on the effect to control how the style is applied.
278
79
 
279
- **Pattern**:
80
+ Use `transition` when all properties share timing. Use `transitionProperties` when each property needs independent `duration`, `delay`, or `easing`.
280
81
 
281
82
  ```typescript
282
83
  {
283
84
  key: '[SOURCE_KEY]',
284
85
  trigger: 'hover',
285
- params: {
286
- type: 'state'
287
- },
288
86
  effects: [
289
87
  {
290
88
  key: '[TARGET_KEY]',
291
- [EFFECT_TYPE]: [EFFECT_DEFINITION],
292
- duration: [DURATION_MS],
293
- iterations: Infinity,
294
- easing: '[EASING_FUNCTION]'
295
- }
296
- ]
297
- }
298
- ```
299
-
300
- **Variables**:
301
-
302
- - Same as Rule 1
303
-
304
- **Use Cases for State Pattern**:
305
-
306
- - Controlling loop animations
307
- - Pausing video effects
308
- - Interactive loading spinners
309
- - Continuous animation control
310
-
311
- **Default Values**:
312
-
313
- - `type`: 'state'
314
- - `iterations`: Infinity
315
- - `DURATION_MS`: 2000 (longer for smooth loops)
316
- - `EASING_FUNCTION`: 'linear' (for continuous motion)
317
-
318
- **Example Generations**:
319
-
320
- ```typescript
321
- // Rotating loader that plays on hover and pauses on mouse leave
322
- {
323
- key: 'loading-spinner',
324
- trigger: 'hover',
325
- params: {
326
- type: 'state'
327
- },
328
- effects: [
329
- {
330
- key: 'loading-spinner',
331
- keyframeEffect: {
332
- name: 'spin',
333
- keyframes: [
334
- { transform: 'rotate(0deg)' },
335
- { transform: 'rotate(360deg)' }
89
+ stateAction: '[STATE_ACTION]',
90
+
91
+ // --- pick ONE of the two transition forms ---
92
+ transition: {
93
+ duration: [DURATION_MS],
94
+ delay: [DELAY_MS],
95
+ easing: '[EASING_FUNCTION]',
96
+ styleProperties: [
97
+ { name: '[CSS_PROP]', value: '[VALUE]' },
98
+ // ... more properties
336
99
  ]
337
100
  },
338
- duration: 2000,
339
- iterations: Infinity,
340
- easing: 'linear'
341
- }
342
- ]
343
- }
344
-
345
- // Pulsing element that plays on hover and pauses on mouse leave
346
- {
347
- key: 'live-indicator',
348
- trigger: 'hover',
349
- params: {
350
- type: 'state'
351
- },
352
- effects: [
353
- {
354
- key: 'live-indicator',
355
- namedEffect: {
356
- type: 'Pulse'
357
- },
358
- duration: 1500,
359
- iterations: Infinity,
360
- easing: 'ease-in-out'
361
- }
362
- ]
363
- }
364
- ```
365
-
366
- ## Rule 5: Multi-Target Hover Effects
367
-
368
- **Purpose**: Generate hover interactions that affect multiple elements from a single source
369
-
370
- **Pattern**:
371
-
372
- ```typescript
373
- {
374
- key: '[SOURCE_KEY]',
375
- trigger: 'hover',
376
- params: {
377
- type: '[BEHAVIOR_TYPE]'
378
- },
379
- effects: [
380
- {
381
- key: '[TARGET_1]',
382
- [EFFECT_TYPE]: [EFFECT_DEFINITION_1],
383
- fill: [FILL_1],
384
- reversed: [REVERSED_BOOL_1],
385
- duration: [DURATION_1],
386
- delay: [DELAY_1]
101
+ // OR (when each property needs its own timing)
102
+ transitionProperties: [
103
+ {
104
+ name: '[CSS_PROP]',
105
+ value: '[VALUE]',
106
+ duration: [DURATION_MS],
107
+ delay: [DELAY_MS],
108
+ easing: '[EASING_FUNCTION]'
109
+ },
110
+ // ... more properties
111
+ ]
387
112
  },
388
- {
389
- key: '[TARGET_2]',
390
- [EFFECT_TYPE]: [EFFECT_DEFINITION_2],
391
- fill: [FILL_2],
392
- reversed: [REVERSED_BOOL_2],
393
- duration: [DURATION_2],
394
- delay: [DELAY_2]
395
- }
113
+ // additional effects targeting other elements can be added here
396
114
  ]
397
115
  }
398
116
  ```
399
117
 
400
- **Variables**:
401
-
402
- - `[BEHAVIOR_TYPE]`: type of behavior for the effect. use `alternate`, `repeat`, or `state` according to the previous rules.
403
- - `[FILL_N]`: Optional fill value for the Nth effect - same as CSS animation-fill-mode (e.g. 'both', 'forwards', 'backwards').
404
- - `[REVERSED_BOOL_N]`: Same as `[REVERSED_BOOL]` from Rule 2 only for the Nth effect.
405
- - `[DURATION_N]`: Same as `[DURATION_MS]` from Rule 1 only for the Nth effect.
406
- - `[DELAY_N]`: Delay in milliseconds of the Nth effect.
118
+ ### Variables
407
119
 
408
- **Use Cases**:
120
+ - `[SOURCE_KEY]` / `[TARGET_KEY]` — same as Rule 1.
121
+ - `[STATE_ACTION]` — `stateAction` on the effect. One of:
122
+ - `'toggle'` — applies the style state on enter, removes on leave. Default.
123
+ - `'add'` — applies the style state on enter. Leave does NOT remove it.
124
+ - `'remove'` — removes a previously applied style state on enter. Use with provided `effectId` to map to a matching interaction with `add` and effect with same `effectId`.
125
+ - `'clear'` — clears all previously applied style states on enter. Use to reset multiple stacked `'add'` style changes at once (e.g. a "reset" hover area that undoes several accumulated states).
126
+ - `[CSS_PROP]` — CSS property name as a string in camelCase format (e.g. `'backgroundColor'`, `'borderRadius'`, `'opacity'`).
127
+ - `[VALUE]` — target CSS value for the property.
128
+ - `[DURATION_MS]` — transition duration in milliseconds.
129
+ - `[DELAY_MS]` — optional transition delay in milliseconds.
130
+ - `[EASING_FUNCTION]` — CSS easing string, or named easing from `@wix/motion`.
409
131
 
410
- - Card hover affecting image, text, and button
411
- - Navigation item hover affecting icon and text
412
- - Complex component state changes
413
-
414
- **Timing Strategies**:
132
+ ---
415
133
 
416
- - Simultaneous: All delays = 0
417
- - Staggered: Incrementing delays (0, 50, 100ms)
418
- - Sequential: Non-overlapping delays
134
+ ## Rule 3: customEffect (TimeEffect)
419
135
 
420
- **Example Generations**:
136
+ Use `customEffect` when you need imperative control over the animation (e.g. counters, canvas drawing, custom DOM manipulation). The callback receives the target element and a `progress` value (0–1) driven by the animation timeline.
421
137
 
422
138
  ```typescript
423
- // Product card with multiple targets
424
139
  {
425
- key: 'product-card',
140
+ key: '[SOURCE_KEY]',
426
141
  trigger: 'hover',
427
- params: {
428
- type: 'alternate'
429
- },
430
142
  effects: [
431
143
  {
432
- key: 'product-card',
433
- keyframeEffect: {
434
- name: 'product-card-move',
435
- keyframes: [
436
- { transform: 'translateY(0)' },
437
- { transform: 'translateY(-8px)' }
438
- ]
439
- },
440
- fill: 'both',
441
- duration: 200,
442
- delay: 0
443
- },
444
- {
445
- key: 'product-image',
446
- keyframeEffect: {
447
- name: 'product-image-scale',
448
- keyframes: [
449
- { transform: 'scale(1)' },
450
- { transform: 'scale(1.05)' }
451
- ]
452
- },
453
- fill: 'both',
454
- duration: 300,
455
- delay: 50
456
- },
457
- {
458
- key: 'product-title',
459
- keyframeEffect: {
460
- name: 'product-title-color',
461
- keyframes: [
462
- { color: '#374151' },
463
- { color: '#2563eb' }
464
- ]
465
- },
466
- fill: 'both',
467
- duration: 150,
468
- delay: 100
144
+ key: '[TARGET_KEY]',
145
+ triggerType: '[TRIGGER_TYPE]',
146
+ customEffect: [CUSTOM_EFFECT_CALLBACK],
147
+ duration: [DURATION_MS],
148
+ easing: '[EASING_FUNCTION]'
469
149
  },
470
- {
471
- key: 'add-to-cart-btn',
472
- keyframeEffect: {
473
- name: 'button-fade',
474
- keyframes: [
475
- { opacity: '0', transform: 'translateY(10px)' },
476
- { opacity: '1', transform: 'translateY(0)' }
477
- ]
478
- },
479
- fill: 'both',
480
- duration: 200,
481
- delay: 150
482
- }
150
+ // additional effects targeting other elements can be added here
483
151
  ]
484
152
  }
485
153
  ```
486
154
 
487
- ## Rule 6: Hover with Sequence (Staggered Multi-Target)
155
+ ### Variables
488
156
 
489
- **Purpose**: Hover interactions that stagger animations across multiple targets using a sequence instead of manual delays.
157
+ - `[SOURCE_KEY]` / `[TARGET_KEY]` / `[TRIGGER_TYPE]` same as Rule 1.
158
+ - `[CUSTOM_EFFECT_CALLBACK]` — function with signature `(target: HTMLElement, progress: number) => void`. Called on each animation frame with the target element and `progress` from 0 to 1.
159
+ - `[DURATION_MS]` — animation duration in milliseconds.
160
+ - `[EASING_FUNCTION]` — CSS easing string, or named easing from `@wix/motion`.
490
161
 
491
- **When to Apply**:
162
+ ---
492
163
 
493
- - When hovering a container should stagger-animate its children
494
- - For list item hover effects with coordinated timing
495
- - When you want easing-controlled stagger on hover
164
+ ## Rule 4: Sequences
496
165
 
497
- **Pattern**:
166
+ Use sequences when a hover should sync/stagger animations across multiple elements. Set `triggerType` on the sequence config to control playback behavior.
498
167
 
499
168
  ```typescript
500
169
  {
501
170
  key: '[SOURCE_KEY]',
502
171
  trigger: 'hover',
503
- params: {
504
- type: 'repeat'
505
- },
506
172
  sequences: [
507
173
  {
174
+ triggerType: '[TRIGGER_TYPE]',
508
175
  offset: [OFFSET_MS],
509
176
  offsetEasing: '[OFFSET_EASING]',
510
177
  effects: [
511
- {
512
- effectId: '[EFFECT_ID]',
513
- listContainer: '[LIST_CONTAINER_SELECTOR]'
514
- }
178
+ [EFFECT_DEFINTION],
179
+ // .. more effects as necessary
515
180
  ]
516
181
  }
517
182
  ]
518
183
  }
519
184
  ```
520
185
 
521
- **Example - Hover Card Grid Stagger**:
522
-
523
- ```typescript
524
- {
525
- key: 'card-grid',
526
- trigger: 'hover',
527
- params: { type: 'repeat' },
528
- sequences: [
529
- {
530
- offset: 80,
531
- offsetEasing: 'sineOut',
532
- effects: [
533
- {
534
- effectId: 'item-pop',
535
- listContainer: '.card-grid-items'
536
- }
537
- ]
538
- }
539
- ]
540
- }
541
- ```
542
-
543
- ```typescript
544
- effects: {
545
- 'item-pop': {
546
- duration: 400,
547
- easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
548
- keyframeEffect: {
549
- name: 'item-pop',
550
- keyframes: [
551
- { transform: 'translateY(16px) scale(0.95)', opacity: 0 },
552
- { transform: 'translateY(0) scale(1)', opacity: 1 }
553
- ]
554
- }
555
- }
556
- }
557
- ```
558
-
559
- ---
560
-
561
- ## Best Practices for Hover Rules
562
-
563
- ### Timing and Pattern Guidelines
564
-
565
- 1. **Keep durations short** (100-400ms) for responsiveness
566
-
567
- ### User Experience Guidelines
568
-
569
- 1. **Use 'alternate' type** for most hover effects (natural enter/leave)
570
- 2. **Use 'repeat' sparingly** - can be annoying if overused
571
- 3. **Use 'state' for controlling** ongoing animations
572
- 4. **Stagger multi-target effects** for more polished feel
573
-
574
- ### Timing Recommendations
575
-
576
- - **Micro-interactions**: 100-200ms
577
- - **Button hovers**: 200-300ms
578
- - **Card/image effects**: 300-400ms
579
- - **Complex multi-target**: 200-500ms total
580
-
581
- ### Easing Recommendations
582
-
583
- - **Enter animations**: 'ease-out' (quick start, slow end)
584
- - **Interactive elements**: 'ease-in-out' (smooth both ways)
585
- - **Attention effects**: 'ease-in-out' (natural feel)
586
- - **Continuous motion**: 'linear' (consistent speed)
587
-
588
- ## Accessibility
589
-
590
- Use `@wix/interact`'s `conditions` API to skip hover animations for users who prefer reduced motion. Define a `prefers-motion` condition and reference it on any interaction that should be suppressed:
591
-
592
- ```typescript
593
- {
594
- conditions: {
595
- 'prefers-motion': { type: 'media', predicate: '(prefers-reduced-motion: no-preference)' }
596
- },
597
- interactions: [
598
- {
599
- key: 'card',
600
- trigger: 'hover',
601
- conditions: ['prefers-motion'], // skipped when reduced-motion is preferred
602
- effects: [/* ... */]
603
- }
604
- ]
605
- }
606
- ```
607
-
608
- For pointer-primary devices only, also consider adding a `hover-capable` condition:
609
-
610
- ```typescript
611
- 'hover-capable': { type: 'media', predicate: '(hover: hover)' }
612
- ```
186
+ ### Variables
613
187
 
614
- Use `trigger: 'interest'` instead of `'hover'` to also handle keyboard focus, which is the accessible equivalent of hover.
188
+ - `[SOURCE_KEY]` / `[TRIGGER_TYPE]` same as Rule 1. `triggerType` is set on the sequence config, not on individual effects within the sequence.
189
+ - `[OFFSET_MS]` — time offset for staggering each child's animation start, in milliseconds.
190
+ - `[OFFSET_EASING]` — easing curve for the offset staggering distribution. CSS easing string, or named easing from `@wix/motion`. Defaults to `'linear'`.
191
+ - `[EFFECT_DEFINTION]` — a definition of or a reference to a time-based animation effect.