@wix/interact 1.93.0 → 2.0.0-rc.4
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.
- package/dist/cjs/index.js +2 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react.js +15 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/web.js +2 -0
- package/dist/cjs/web.js.map +1 -0
- package/dist/es/index.js +8 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react.js +650 -0
- package/dist/es/react.js.map +1 -0
- package/dist/es/web.js +56 -0
- package/dist/es/web.js.map +1 -0
- package/dist/index-BoEj_7uB.js +18 -0
- package/dist/index-BoEj_7uB.js.map +1 -0
- package/dist/index-DUTdIvfw.mjs +7969 -0
- package/dist/index-DUTdIvfw.mjs.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types/core/Interact.d.ts +25 -10
- package/dist/types/core/Interact.d.ts.map +1 -0
- package/dist/types/core/InteractionController.d.ts +24 -0
- package/dist/types/core/InteractionController.d.ts.map +1 -0
- package/dist/types/core/add.d.ts +4 -3
- package/dist/types/core/add.d.ts.map +1 -0
- package/dist/types/core/css.d.ts +3 -0
- package/dist/types/core/css.d.ts.map +1 -0
- package/dist/types/core/remove.d.ts +3 -1
- package/dist/types/core/remove.d.ts.map +1 -0
- package/dist/types/core/utilities.d.ts +1 -0
- package/dist/types/core/utilities.d.ts.map +1 -0
- package/dist/types/dom/api.d.ts +3 -0
- package/dist/types/dom/api.d.ts.map +1 -0
- package/dist/types/handlers/animationEnd.d.ts +3 -2
- package/dist/types/handlers/animationEnd.d.ts.map +1 -0
- package/dist/types/handlers/click.d.ts +3 -2
- package/dist/types/handlers/click.d.ts.map +1 -0
- package/dist/types/handlers/hover.d.ts +3 -2
- package/dist/types/handlers/hover.d.ts.map +1 -0
- package/dist/types/handlers/index.d.ts +1 -0
- package/dist/types/handlers/index.d.ts.map +1 -0
- package/dist/types/handlers/pointerMove.d.ts +3 -2
- package/dist/types/handlers/pointerMove.d.ts.map +1 -0
- package/dist/types/handlers/utilities.d.ts +1 -0
- package/dist/types/handlers/utilities.d.ts.map +1 -0
- package/dist/types/handlers/viewEnter.d.ts +3 -2
- package/dist/types/handlers/viewEnter.d.ts.map +1 -0
- package/dist/types/handlers/viewProgress.d.ts +4 -3
- package/dist/types/handlers/viewProgress.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/react/Interaction.d.ts +10 -0
- package/dist/types/react/Interaction.d.ts.map +1 -0
- package/dist/types/react/index.d.ts +8 -0
- package/dist/types/react/index.d.ts.map +1 -0
- package/dist/types/react/interactRef.d.ts +3 -0
- package/dist/types/react/interactRef.d.ts.map +1 -0
- package/dist/types/types.d.ts +31 -12
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +2 -1
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/{InteractElement.d.ts → web/InteractElement.d.ts} +117 -77
- package/dist/types/web/InteractElement.d.ts.map +1 -0
- package/dist/types/web/defineInteractElement.d.ts +2 -0
- package/dist/types/web/defineInteractElement.d.ts.map +1 -0
- package/dist/types/web/index.d.ts +6 -0
- package/dist/types/web/index.d.ts.map +1 -0
- package/docs/README.md +211 -0
- package/docs/advanced/README.md +164 -0
- package/docs/api/README.md +157 -0
- package/docs/api/element-selection.md +607 -0
- package/docs/api/functions.md +638 -0
- package/docs/api/interact-class.md +663 -0
- package/docs/api/interact-element.md +565 -0
- package/docs/api/interaction-controller.md +450 -0
- package/docs/api/types.md +957 -0
- package/docs/examples/README.md +212 -0
- package/docs/examples/click-interactions.md +977 -0
- package/docs/examples/entrance-animations.md +935 -0
- package/docs/examples/hover-effects.md +930 -0
- package/docs/examples/list-patterns.md +737 -0
- package/docs/guides/README.md +49 -0
- package/docs/guides/conditions-and-media-queries.md +1068 -0
- package/docs/guides/configuration-structure.md +726 -0
- package/docs/guides/custom-elements.md +327 -0
- package/docs/guides/effects-and-animations.md +634 -0
- package/docs/guides/getting-started.md +379 -0
- package/docs/guides/lists-and-dynamic-content.md +713 -0
- package/docs/guides/state-management.md +747 -0
- package/docs/guides/understanding-triggers.md +690 -0
- package/docs/integration/README.md +264 -0
- package/docs/integration/react.md +605 -0
- package/package.json +73 -56
- package/rules/Integration.md +255 -0
- package/rules/click-rules.md +533 -0
- package/rules/full-lean.md +346 -0
- package/rules/hover-rules.md +593 -0
- package/rules/pointermove-rules.md +1341 -0
- package/rules/scroll-list-rules.md +900 -0
- package/rules/viewenter-rules.md +1015 -0
- package/rules/viewprogress-rules.md +1044 -0
- package/dist/cjs/InteractElement.js +0 -163
- package/dist/cjs/InteractElement.js.map +0 -1
- package/dist/cjs/__tests__/interact.spec.js +0 -2094
- package/dist/cjs/__tests__/interact.spec.js.map +0 -1
- package/dist/cjs/__tests__/viewEnter.spec.js +0 -207
- package/dist/cjs/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/cjs/core/Interact.js +0 -257
- package/dist/cjs/core/Interact.js.map +0 -1
- package/dist/cjs/core/add.js +0 -250
- package/dist/cjs/core/add.js.map +0 -1
- package/dist/cjs/core/remove.js +0 -35
- package/dist/cjs/core/remove.js.map +0 -1
- package/dist/cjs/core/utilities.js +0 -16
- package/dist/cjs/core/utilities.js.map +0 -1
- package/dist/cjs/external-types.d.js +0 -2
- package/dist/cjs/external-types.d.js.map +0 -1
- package/dist/cjs/handlers/animationEnd.js +0 -37
- package/dist/cjs/handlers/animationEnd.js.map +0 -1
- package/dist/cjs/handlers/click.js +0 -122
- package/dist/cjs/handlers/click.js.map +0 -1
- package/dist/cjs/handlers/hover.js +0 -147
- package/dist/cjs/handlers/hover.js.map +0 -1
- package/dist/cjs/handlers/index.js +0 -32
- package/dist/cjs/handlers/index.js.map +0 -1
- package/dist/cjs/handlers/pointerMove.js +0 -49
- package/dist/cjs/handlers/pointerMove.js.map +0 -1
- package/dist/cjs/handlers/utilities.js +0 -49
- package/dist/cjs/handlers/utilities.js.map +0 -1
- package/dist/cjs/handlers/viewEnter.js +0 -131
- package/dist/cjs/handlers/viewEnter.js.map +0 -1
- package/dist/cjs/handlers/viewProgress.js +0 -79
- package/dist/cjs/handlers/viewProgress.js.map +0 -1
- package/dist/cjs/test-types.d.js +0 -2
- package/dist/cjs/test-types.d.js.map +0 -1
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/types.js.map +0 -1
- package/dist/cjs/utils.js +0 -98
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/InteractElement.js +0 -157
- package/dist/esm/InteractElement.js.map +0 -1
- package/dist/esm/__tests__/interact.spec.js +0 -2102
- package/dist/esm/__tests__/interact.spec.js.map +0 -1
- package/dist/esm/__tests__/viewEnter.spec.js +0 -210
- package/dist/esm/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/esm/core/Interact.js +0 -251
- package/dist/esm/core/Interact.js.map +0 -1
- package/dist/esm/core/add.js +0 -245
- package/dist/esm/core/add.js.map +0 -1
- package/dist/esm/core/remove.js +0 -30
- package/dist/esm/core/remove.js.map +0 -1
- package/dist/esm/core/utilities.js +0 -14
- package/dist/esm/core/utilities.js.map +0 -1
- package/dist/esm/external-types.d.js +0 -2
- package/dist/esm/external-types.d.js.map +0 -1
- package/dist/esm/handlers/animationEnd.js +0 -33
- package/dist/esm/handlers/animationEnd.js.map +0 -1
- package/dist/esm/handlers/click.js +0 -122
- package/dist/esm/handlers/click.js.map +0 -1
- package/dist/esm/handlers/hover.js +0 -147
- package/dist/esm/handlers/hover.js.map +0 -1
- package/dist/esm/handlers/index.js +0 -27
- package/dist/esm/handlers/index.js.map +0 -1
- package/dist/esm/handlers/pointerMove.js +0 -48
- package/dist/esm/handlers/pointerMove.js.map +0 -1
- package/dist/esm/handlers/utilities.js +0 -43
- package/dist/esm/handlers/utilities.js.map +0 -1
- package/dist/esm/handlers/viewEnter.js +0 -133
- package/dist/esm/handlers/viewEnter.js.map +0 -1
- package/dist/esm/handlers/viewProgress.js +0 -75
- package/dist/esm/handlers/viewProgress.js.map +0 -1
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/test-types.d.js +0 -2
- package/dist/esm/test-types.d.js.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js +0 -92
- package/dist/esm/utils.js.map +0 -1
- package/dist/types/__tests__/interact.spec.d.ts +0 -1
- package/dist/types/__tests__/viewEnter.spec.d.ts +0 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
# Understanding Triggers
|
|
2
|
+
|
|
3
|
+
Triggers are the heart of `@wix/interact` - they define when an interaction should start. This guide covers all 9 trigger types and how to use them effectively.
|
|
4
|
+
|
|
5
|
+
## Overview of Trigger Types
|
|
6
|
+
|
|
7
|
+
| Trigger | Description | Use Cases |
|
|
8
|
+
|---------|-------------|-----------|
|
|
9
|
+
| `hover` | Mouse enter/leave events | Button highlights, image overlays |
|
|
10
|
+
| `click` | Mouse click events | Toggles, state changes, menus |
|
|
11
|
+
| `interest` | Accessibility-friendly hover (focus events)
|
|
12
|
+
| `activate` | Accessibility-friendly click (keyboard Enter/Space)
|
|
13
|
+
| `viewEnter` | Element enters viewport | Entrance animations, lazy loading |
|
|
14
|
+
| `pageVisible` | Page becomes visible | Loop animations, Auto-play videos |
|
|
15
|
+
| `animationEnd` | Previous animation completes | Animation sequences, chaining |
|
|
16
|
+
| `viewProgress` | Scroll progress through element | Parallax, progress bars |
|
|
17
|
+
| `pointerMove` | Mouse movement over element | Interactive cards, 3D effects |
|
|
18
|
+
|
|
19
|
+
## 1. Hover Trigger
|
|
20
|
+
|
|
21
|
+
The `hover` trigger responds to mouse enter and leave events.
|
|
22
|
+
|
|
23
|
+
### Basic Usage
|
|
24
|
+
```typescript
|
|
25
|
+
{
|
|
26
|
+
key: 'my-button',
|
|
27
|
+
trigger: 'hover',
|
|
28
|
+
effects: [
|
|
29
|
+
{
|
|
30
|
+
keyframeEffect: {
|
|
31
|
+
name: 'scale',
|
|
32
|
+
keyframes: [
|
|
33
|
+
{ scale: 2 }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
duration: 200
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Advanced Options
|
|
43
|
+
```typescript
|
|
44
|
+
{
|
|
45
|
+
key: 'my-card',
|
|
46
|
+
trigger: 'hover',
|
|
47
|
+
params: {
|
|
48
|
+
type: 'alternate'
|
|
49
|
+
},
|
|
50
|
+
effects: [
|
|
51
|
+
{
|
|
52
|
+
keyframeEffect: {
|
|
53
|
+
name: 'shadow',
|
|
54
|
+
keyframes: [
|
|
55
|
+
{ transform: 'scale(1)', boxShadow: 'none' },
|
|
56
|
+
{ transform: 'scale(1.05)', boxShadow: '0 10px 20px rgba(0,0,0,0.1)' }
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
duration: 300,
|
|
60
|
+
easing: 'ease-out'
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Hover Behavior Types
|
|
67
|
+
- **`alternate`** (default): Plays forward on enter, reverses on leave
|
|
68
|
+
- **`repeat`**: Restarts animation each time
|
|
69
|
+
- **`once`**: Only plays once, then stops
|
|
70
|
+
- **`state`**: Pauses/resumes on hover
|
|
71
|
+
|
|
72
|
+
### Real-World Example: Image Overlay
|
|
73
|
+
```typescript
|
|
74
|
+
{
|
|
75
|
+
key: 'image-card',
|
|
76
|
+
trigger: 'hover',
|
|
77
|
+
params: { type: 'alternate' },
|
|
78
|
+
effects: [
|
|
79
|
+
{
|
|
80
|
+
key: 'image-overlay',
|
|
81
|
+
keyframeEffect: {
|
|
82
|
+
name: 'slide-hover',
|
|
83
|
+
keyframes: [
|
|
84
|
+
{ opacity: '0', transform: 'translateY(20px)' },
|
|
85
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
duration: 250,
|
|
89
|
+
easing: 'ease-out'
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 2. Click Trigger
|
|
96
|
+
|
|
97
|
+
The `click` trigger responds to mouse click events and supports multiple behavior modes.
|
|
98
|
+
|
|
99
|
+
### Basic Usage
|
|
100
|
+
```typescript
|
|
101
|
+
{
|
|
102
|
+
key: 'toggle-button',
|
|
103
|
+
trigger: 'click',
|
|
104
|
+
effects: [
|
|
105
|
+
{
|
|
106
|
+
key: 'sidebar',
|
|
107
|
+
keyframeEffect: {
|
|
108
|
+
name: 'sidebar-toggle',
|
|
109
|
+
keyframes: [
|
|
110
|
+
{ transform: 'translateX(-100%)' },
|
|
111
|
+
{ transform: 'translateX(0)' }
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
duration: 300
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Click Behavior Types
|
|
121
|
+
```typescript
|
|
122
|
+
{
|
|
123
|
+
key: 'accordion-header',
|
|
124
|
+
trigger: 'click',
|
|
125
|
+
params: {
|
|
126
|
+
type: 'alternate'
|
|
127
|
+
},
|
|
128
|
+
effects: [
|
|
129
|
+
{
|
|
130
|
+
key: 'accordion-content',
|
|
131
|
+
keyframeEffect: {
|
|
132
|
+
name: 'accordion',
|
|
133
|
+
keyframes: [
|
|
134
|
+
{ clipPath: 'inset(0 0 100% 0)', translate: '0 -100%' },
|
|
135
|
+
{ clipPath: 'inset(0 0 0 0)', translate: '0 0' }
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
duration: 400
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- **`alternate`** (default): First click plays forward, subsequent click reverses
|
|
145
|
+
- **`repeat`**: Each click restarts the animation
|
|
146
|
+
- **`once`**: Only responds to the first click
|
|
147
|
+
- **`state`**: First click plays, subsequent clicks pause/resume
|
|
148
|
+
|
|
149
|
+
### Real-World Example: Menu Toggle
|
|
150
|
+
```typescript
|
|
151
|
+
{
|
|
152
|
+
key: 'menu-button',
|
|
153
|
+
trigger: 'click',
|
|
154
|
+
params: { type: 'alternate' },
|
|
155
|
+
effects: [
|
|
156
|
+
{
|
|
157
|
+
key: 'menu-icon',
|
|
158
|
+
keyframeEffect: {
|
|
159
|
+
name: 'spin',
|
|
160
|
+
keyframes: [
|
|
161
|
+
{ transform: 'rotate(0deg)' },
|
|
162
|
+
{ transform: 'rotate(45deg)' }
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
duration: 200,
|
|
166
|
+
effectId: 'menu-icon-rotate'
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
key: 'mobile-menu',
|
|
170
|
+
keyframeEffect: {
|
|
171
|
+
name: 'slide',
|
|
172
|
+
keyframes: [
|
|
173
|
+
{ opacity: '0', transform: 'translateX(100%)' },
|
|
174
|
+
{ opacity: '1', transform: 'translateX(0)' }
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
duration: 300,
|
|
178
|
+
delay: 100
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 3. Interest Trigger
|
|
185
|
+
|
|
186
|
+
The `interest` trigger is an accessibility-friendly version of `hover` that responds to both mouse hover and keyboard focus events. This makes interactions accessible to keyboard users and screen reader users.
|
|
187
|
+
|
|
188
|
+
### Basic Usage
|
|
189
|
+
```typescript
|
|
190
|
+
{
|
|
191
|
+
key: 'my-button',
|
|
192
|
+
trigger: 'interest',
|
|
193
|
+
effects: [
|
|
194
|
+
{
|
|
195
|
+
keyframeEffect: {
|
|
196
|
+
name: 'scale',
|
|
197
|
+
keyframes: [
|
|
198
|
+
{ scale: 2 }
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
duration: 200
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### How It Works
|
|
208
|
+
- **Mouse users**: Triggers on `mouseenter` and `mouseleave` events (same as `hover`)
|
|
209
|
+
- **Keyboard users**: Triggers on `focusin` and `focusout` events
|
|
210
|
+
- Automatically sets `tabIndex={0}` on the element to make it keyboard-focusable
|
|
211
|
+
|
|
212
|
+
## 4. Activate Trigger
|
|
213
|
+
|
|
214
|
+
The `activate` trigger is an accessibility-friendly version of `click` that responds to both mouse clicks and keyboard activation (Enter/Space keys). This makes click interactions accessible to keyboard users.
|
|
215
|
+
|
|
216
|
+
### Basic Usage
|
|
217
|
+
```typescript
|
|
218
|
+
{
|
|
219
|
+
key: 'toggle-button',
|
|
220
|
+
trigger: 'activate',
|
|
221
|
+
effects: [
|
|
222
|
+
{
|
|
223
|
+
key: 'sidebar',
|
|
224
|
+
keyframeEffect: {
|
|
225
|
+
name: 'sidebar-toggle',
|
|
226
|
+
keyframes: [
|
|
227
|
+
{ transform: 'translateX(-100%)' },
|
|
228
|
+
{ transform: 'translateX(0)' }
|
|
229
|
+
]
|
|
230
|
+
},
|
|
231
|
+
duration: 300
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### How It Works
|
|
238
|
+
- **Mouse users**: Triggers on `click` events (same as `click`)
|
|
239
|
+
- **Keyboard users**: Triggers on `keydown` events for Enter and Space keys
|
|
240
|
+
- Automatically sets `tabIndex={0}` on the element to make it keyboard-focusable
|
|
241
|
+
|
|
242
|
+
## 5. ViewEnter Trigger
|
|
243
|
+
|
|
244
|
+
The `viewEnter` trigger uses Intersection Observer to detect when elements enter the viewport.
|
|
245
|
+
|
|
246
|
+
### Basic Usage
|
|
247
|
+
```typescript
|
|
248
|
+
{
|
|
249
|
+
key: 'section-title',
|
|
250
|
+
trigger: 'viewEnter',
|
|
251
|
+
effects: [
|
|
252
|
+
{
|
|
253
|
+
key: 'section-title',
|
|
254
|
+
namedEffect: 'FadeIn',
|
|
255
|
+
duration: 800
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Advanced Configuration
|
|
262
|
+
```typescript
|
|
263
|
+
{
|
|
264
|
+
key: 'hero-image',
|
|
265
|
+
trigger: 'viewEnter',
|
|
266
|
+
params: {
|
|
267
|
+
type: 'once', // 'once' | 'repeat' | 'alternate'
|
|
268
|
+
threshold: 0.5, // 0-1, how much of element must be visible
|
|
269
|
+
inset: '-50px' // Margin around viewport
|
|
270
|
+
},
|
|
271
|
+
effects: [
|
|
272
|
+
{
|
|
273
|
+
key: 'hero-image',
|
|
274
|
+
keyframeEffect: {
|
|
275
|
+
name: 'slide-in',
|
|
276
|
+
keyframes: [
|
|
277
|
+
{ opacity: '0', transform: 'translateY(50px)' },
|
|
278
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
279
|
+
]
|
|
280
|
+
},
|
|
281
|
+
duration: 1000,
|
|
282
|
+
easing: 'ease-out'
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### ViewEnter Behavior Types
|
|
289
|
+
- **`once`** (recommended): Triggers only when element first enters viewport
|
|
290
|
+
- **`repeat`**: Triggers every time element enters viewport
|
|
291
|
+
- **`alternate`**: Plays forward on enter, reverses on exit
|
|
292
|
+
|
|
293
|
+
### Real-World Example: Staggered Card Animation
|
|
294
|
+
```typescript
|
|
295
|
+
// Configure multiple cards with delays
|
|
296
|
+
const cardAnimations = [
|
|
297
|
+
{
|
|
298
|
+
key: 'card-1',
|
|
299
|
+
trigger: 'viewEnter',
|
|
300
|
+
params: { type: 'once', threshold: 0.3 },
|
|
301
|
+
effects: [{
|
|
302
|
+
key: 'card-1',
|
|
303
|
+
keyframeEffect: {
|
|
304
|
+
name: 'slide-up',
|
|
305
|
+
keyframes: [
|
|
306
|
+
{ opacity: '0', transform: 'translateY(30px)' },
|
|
307
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
duration: 600,
|
|
311
|
+
delay: 0,
|
|
312
|
+
easing: 'ease-out'
|
|
313
|
+
}]
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
key: 'card-2',
|
|
317
|
+
trigger: 'viewEnter',
|
|
318
|
+
params: { type: 'once', threshold: 0.3 },
|
|
319
|
+
effects: [{
|
|
320
|
+
key: 'card-2',
|
|
321
|
+
keyframeEffect: {
|
|
322
|
+
name: 'slide-up',
|
|
323
|
+
keyframes: [
|
|
324
|
+
{ opacity: '0', transform: 'translateY(30px)' },
|
|
325
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
326
|
+
]
|
|
327
|
+
},
|
|
328
|
+
duration: 600,
|
|
329
|
+
delay: 100,
|
|
330
|
+
easing: 'ease-out'
|
|
331
|
+
}]
|
|
332
|
+
}
|
|
333
|
+
];
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## 6. PageVisible Trigger
|
|
337
|
+
|
|
338
|
+
TBD
|
|
339
|
+
|
|
340
|
+
## 7. ViewProgress Trigger
|
|
341
|
+
|
|
342
|
+
The `viewProgress` trigger creates scroll-driven animations as elements move through the viewport.
|
|
343
|
+
|
|
344
|
+
### Basic Usage
|
|
345
|
+
```typescript
|
|
346
|
+
{
|
|
347
|
+
key: 'parallax-element',
|
|
348
|
+
trigger: 'viewProgress',
|
|
349
|
+
effects: [
|
|
350
|
+
{
|
|
351
|
+
key: 'parallax-element',
|
|
352
|
+
keyframeEffect: {
|
|
353
|
+
name: 'parallax',
|
|
354
|
+
keyframes: [
|
|
355
|
+
{ transform: 'translateY(0)' },
|
|
356
|
+
{ transform: 'translateY(-100px)' }
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
// Note: viewProgress uses ranges, not duration
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Advanced Parallax Effect
|
|
366
|
+
```typescript
|
|
367
|
+
{
|
|
368
|
+
key: 'hero-section',
|
|
369
|
+
trigger: 'viewProgress',
|
|
370
|
+
effects: [
|
|
371
|
+
{
|
|
372
|
+
key: 'background-image',
|
|
373
|
+
keyframeEffect: {
|
|
374
|
+
name: 'grayscale',
|
|
375
|
+
keyframes: [
|
|
376
|
+
{ filter: 'grayscale(0)' },
|
|
377
|
+
{ filter: 'grayscale(100%)' }
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
rangeStart: { name: 'exit', offset: { type: 'percentage', value: 0 } },
|
|
381
|
+
rangeEnd: { name: 'exit', offset: { type: 'percentage', value: 100 } }
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
key: 'foreground-text',
|
|
385
|
+
keyframeEffect: {
|
|
386
|
+
name: 'fade-zoom',
|
|
387
|
+
keyframes: [
|
|
388
|
+
{ opacity: '1', transform: 'scale(1)' },
|
|
389
|
+
{ opacity: '0', transform: 'scale(0.8)' }
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
rangeStart: { name: 'exit', offset: { type: 'percentage', value: 0 } },
|
|
393
|
+
rangeEnd: { name: 'exit', offset: { type: 'percentage', value: 100 } }
|
|
394
|
+
}
|
|
395
|
+
]
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Real-World Example: Reading Progress Bar
|
|
400
|
+
```typescript
|
|
401
|
+
{
|
|
402
|
+
key: 'article-content',
|
|
403
|
+
trigger: 'viewProgress',
|
|
404
|
+
effects: [
|
|
405
|
+
{
|
|
406
|
+
key: 'progress-bar',
|
|
407
|
+
keyframeEffect: {
|
|
408
|
+
name: 'progress-animation',
|
|
409
|
+
keyframes: [
|
|
410
|
+
{ transform: 'scaleX(0)' },
|
|
411
|
+
{ transform: 'scaleX(1)' }
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
rangeStart: { name: 'cover', offset: { type: 'percentage', value: 0 } },
|
|
415
|
+
rangeEnd: { name: 'cover', offset: { type: 'percentage', value: 100 } }
|
|
416
|
+
}
|
|
417
|
+
]
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## 8. PointerMove Trigger
|
|
422
|
+
|
|
423
|
+
The `pointerMove` trigger creates mouse-following effects and 3D interactions.
|
|
424
|
+
|
|
425
|
+
### Basic Usage
|
|
426
|
+
```typescript
|
|
427
|
+
{
|
|
428
|
+
key: 'interactive-card',
|
|
429
|
+
trigger: 'pointerMove',
|
|
430
|
+
effects: [
|
|
431
|
+
{
|
|
432
|
+
key: 'interactive-card',
|
|
433
|
+
keyframeEffect: {
|
|
434
|
+
name: 'tilt-card',
|
|
435
|
+
keyframes: [
|
|
436
|
+
{ transform: 'perspective(800px) rotateX(40deg) rotateY(-40deg)' },
|
|
437
|
+
{ transform: 'perspective(800px) rotateX(-40deg) rotateY(40deg)' }
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
]
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Advanced Configuration
|
|
446
|
+
```typescript
|
|
447
|
+
{
|
|
448
|
+
key: 'card-section',
|
|
449
|
+
trigger: 'pointerMove',
|
|
450
|
+
params: {
|
|
451
|
+
hitArea: 'self' // 'self' | 'root'
|
|
452
|
+
},
|
|
453
|
+
effects: [
|
|
454
|
+
{
|
|
455
|
+
key: 'tilt-card',
|
|
456
|
+
keyframeEffect: {
|
|
457
|
+
name: 'tilt-card',
|
|
458
|
+
keyframes: [
|
|
459
|
+
{ transform: 'perspective(800px) rotateX(40deg) rotateY(-40deg)' },
|
|
460
|
+
{ transform: 'perspective(800px) rotateX(-40deg) rotateY(40deg)' }
|
|
461
|
+
]
|
|
462
|
+
},
|
|
463
|
+
centeredToTarget: true // will place 50% point at center of animation target
|
|
464
|
+
}
|
|
465
|
+
]
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Real-World Example: 3D Product Card
|
|
470
|
+
```typescript
|
|
471
|
+
{
|
|
472
|
+
key: 'product-card',
|
|
473
|
+
trigger: 'pointerMove',
|
|
474
|
+
params: { hitArea: 'self' },
|
|
475
|
+
effects: [
|
|
476
|
+
{
|
|
477
|
+
key: 'tilt-card',
|
|
478
|
+
keyframeEffect: {
|
|
479
|
+
name: 'tilt-card',
|
|
480
|
+
keyframes: [
|
|
481
|
+
{ transform: 'perspective(800px) rotateX(40deg) rotateY(-40deg)' },
|
|
482
|
+
{ transform: 'perspective(800px) rotateX(-40deg) rotateY(40deg)' }
|
|
483
|
+
]
|
|
484
|
+
},
|
|
485
|
+
centeredToTarget: true // will place 50% point at center of animation target
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## 9. AnimationEnd Trigger
|
|
492
|
+
|
|
493
|
+
The `animationEnd` trigger allows you to chain animations by waiting for a previous animation to complete.
|
|
494
|
+
|
|
495
|
+
### Basic Usage
|
|
496
|
+
```typescript
|
|
497
|
+
// First animation
|
|
498
|
+
{
|
|
499
|
+
key: 'sequence-start',
|
|
500
|
+
trigger: 'click',
|
|
501
|
+
effects: [
|
|
502
|
+
{
|
|
503
|
+
key: 'first-element',
|
|
504
|
+
namedEffect: {
|
|
505
|
+
type: 'FadeIn'
|
|
506
|
+
},
|
|
507
|
+
duration: 500,
|
|
508
|
+
effectId: 'fade-in-first' // Required for chaining
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
},
|
|
512
|
+
// Chained animation
|
|
513
|
+
{
|
|
514
|
+
key: 'first-element',
|
|
515
|
+
trigger: 'animationEnd',
|
|
516
|
+
params: {
|
|
517
|
+
effectId: 'fade-in-first' // Must match the effectId above
|
|
518
|
+
},
|
|
519
|
+
effects: [
|
|
520
|
+
{
|
|
521
|
+
key: 'second-element',
|
|
522
|
+
namedEffect: {
|
|
523
|
+
type: 'SlideIn'
|
|
524
|
+
},
|
|
525
|
+
duration: 500,
|
|
526
|
+
effectId: 'slide-in-second'
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Real-World Example: Loading Sequence
|
|
533
|
+
```typescript
|
|
534
|
+
const loadingSequence = [
|
|
535
|
+
{
|
|
536
|
+
key: 'app-logo',
|
|
537
|
+
trigger: 'viewEnter',
|
|
538
|
+
effects: [{
|
|
539
|
+
key: 'app-logo',
|
|
540
|
+
namedEffect: {
|
|
541
|
+
type: 'FadeIn'
|
|
542
|
+
},
|
|
543
|
+
duration: 800,
|
|
544
|
+
effectId: 'logo-appear'
|
|
545
|
+
}]
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
key: 'app-logo',
|
|
549
|
+
trigger: 'animationEnd',
|
|
550
|
+
params: { effectId: 'logo-appear' },
|
|
551
|
+
effects: [{
|
|
552
|
+
key: 'loading-text',
|
|
553
|
+
keyframeEffect: {
|
|
554
|
+
name: 'slide-up',
|
|
555
|
+
keyframes: [
|
|
556
|
+
{ opacity: '0', transform: 'translateY(20px)' },
|
|
557
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
558
|
+
]
|
|
559
|
+
},
|
|
560
|
+
duration: 600,
|
|
561
|
+
easing: 'ease-out',
|
|
562
|
+
effectId: 'text-appear'
|
|
563
|
+
}]
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
key: 'loading-text',
|
|
567
|
+
trigger: 'animationEnd',
|
|
568
|
+
params: { effectId: 'text-appear' },
|
|
569
|
+
effects: [{
|
|
570
|
+
key: 'main-content',
|
|
571
|
+
namedEffect: {
|
|
572
|
+
type: 'FadeIn'
|
|
573
|
+
},
|
|
574
|
+
duration: 1000
|
|
575
|
+
}]
|
|
576
|
+
}
|
|
577
|
+
];
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
## Combining Triggers
|
|
581
|
+
|
|
582
|
+
You can combine multiple triggers on the same element for complex interactions:
|
|
583
|
+
|
|
584
|
+
```typescript
|
|
585
|
+
{
|
|
586
|
+
interactions: [
|
|
587
|
+
// Entrance animation
|
|
588
|
+
{
|
|
589
|
+
key: 'interactive-card',
|
|
590
|
+
trigger: 'viewEnter',
|
|
591
|
+
params: { type: 'once' },
|
|
592
|
+
effects: [{
|
|
593
|
+
key: 'interactive-card',
|
|
594
|
+
namedEffect: {
|
|
595
|
+
type: 'FadeIn'
|
|
596
|
+
},
|
|
597
|
+
duration: 800
|
|
598
|
+
}]
|
|
599
|
+
},
|
|
600
|
+
// Hover effect
|
|
601
|
+
{
|
|
602
|
+
key: 'interactive-card',
|
|
603
|
+
trigger: 'hover',
|
|
604
|
+
effects: [{
|
|
605
|
+
key: 'interactive-card',
|
|
606
|
+
keyframeEffect: {
|
|
607
|
+
name: 'shadow',
|
|
608
|
+
keyframes: [
|
|
609
|
+
{ transform: 'scale(1)', boxShadow: 'none' },
|
|
610
|
+
{ transform: 'scale(1.02)', boxShadow: '0 20px 40px rgba(0 0 0 / 0.1)' }
|
|
611
|
+
]
|
|
612
|
+
},
|
|
613
|
+
duration: 200,
|
|
614
|
+
easing: 'ease-out'
|
|
615
|
+
}]
|
|
616
|
+
},
|
|
617
|
+
// Click action
|
|
618
|
+
{
|
|
619
|
+
key: '#interactive-card',
|
|
620
|
+
trigger: 'click',
|
|
621
|
+
effects: [{
|
|
622
|
+
key: 'card-details',
|
|
623
|
+
keyframeEffect: {
|
|
624
|
+
name: 'slide-down',
|
|
625
|
+
keyframes: [
|
|
626
|
+
{ opacity: '0', transform: 'translateY(-20px)' },
|
|
627
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
628
|
+
]
|
|
629
|
+
},
|
|
630
|
+
duration: 400,
|
|
631
|
+
easing: 'ease-out'
|
|
632
|
+
}]
|
|
633
|
+
}
|
|
634
|
+
]
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## Best Practices
|
|
639
|
+
|
|
640
|
+
### Performance
|
|
641
|
+
1. **Prefer animating hardware-accelerated properties**, i.e. transforms, opacity, and filters
|
|
642
|
+
2. **Avoid animating layout properties**, these are the most costly properties to animate
|
|
643
|
+
3. **Avoid animating custom properties**, since changing them via animation causes a style recalculation
|
|
644
|
+
|
|
645
|
+
### User Experience
|
|
646
|
+
1. **Keep hover animations short** (200-300ms) for responsiveness
|
|
647
|
+
2. **Use meaningful delays** in animation sequences
|
|
648
|
+
3. **Provide visual feedback** for click interactions
|
|
649
|
+
4. **Set appropriate thresholds** for `viewEnter` to avoid premature triggers
|
|
650
|
+
|
|
651
|
+
### Accessibility
|
|
652
|
+
1. **Respect `prefers-reduced-motion`** media query
|
|
653
|
+
2. **Use `activate` instead of `click`** for keyboard accessibility
|
|
654
|
+
3. **Use `interest` instead of `hover`** for keyboard accessibility
|
|
655
|
+
4. **Ensure click targets are accessible** via keyboard
|
|
656
|
+
5. **Don't rely solely on motion** for important information
|
|
657
|
+
6. **Enable accessibility triggers globally** using `Interact.setup({ allowA11yTriggers: true })` to make `click` and `hover` triggers keyboard-accessible
|
|
658
|
+
|
|
659
|
+
## Troubleshooting
|
|
660
|
+
|
|
661
|
+
### Common Issues
|
|
662
|
+
|
|
663
|
+
**Trigger not firing:**
|
|
664
|
+
- Check element exists when `Interact.create()` is called
|
|
665
|
+
- Verify `data-interact-key` matches your CSS selector
|
|
666
|
+
- Ensure element is actually visible for viewport triggers
|
|
667
|
+
|
|
668
|
+
**Animation not smooth:**
|
|
669
|
+
- Use `transform` and `opacity` properties
|
|
670
|
+
- Avoid animating layout properties like `width`/`height`
|
|
671
|
+
- Check for conflicting CSS transitions
|
|
672
|
+
|
|
673
|
+
**ViewEnter not triggering**
|
|
674
|
+
- Since entrance animations use `IntersectionObserver`, if the source element is clipped out, e.g: by a parent's `overflow`, or `clip-path`, or if it's pushed out of the viewport it may never trigger.
|
|
675
|
+
To avoid this either **use a separate target element form the source element, or avoid transforms/clip-path/mask at 0% progress**
|
|
676
|
+
|
|
677
|
+
**ViewEnter triggering multiple times**
|
|
678
|
+
- From same reasons as above, **Use `once` for `viewEnter` triggers**, if the source element is also the target element, since it may re-trigger animations multiple times when animating.
|
|
679
|
+
|
|
680
|
+
**ViewEnter triggering too early/late:**
|
|
681
|
+
- Adjust `threshold` and `inset` parameters
|
|
682
|
+
- Test on different screen sizes
|
|
683
|
+
- Consider content loading delays
|
|
684
|
+
|
|
685
|
+
## Next Steps
|
|
686
|
+
|
|
687
|
+
Now that you understand all trigger types, explore:
|
|
688
|
+
- **[Effects and Animations](./effects-and-animations.md)** - Learn about animation options
|
|
689
|
+
- **[Configuration Structure](./configuration-structure.md)** - Organize complex interactions
|
|
690
|
+
- **[State Management](./state-management.md)** - Advanced state handling techniques
|