@wix/interact 1.93.0 → 2.0.0-rc.2
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-C8QxOkui.mjs +7940 -0
- package/dist/index-C8QxOkui.mjs.map +1 -0
- package/dist/index-DEPRHaUt.js +18 -0
- package/dist/index-DEPRHaUt.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types/core/Interact.d.ts +17 -7
- package/dist/types/core/Interact.d.ts.map +1 -0
- package/dist/types/core/InteractionController.d.ts +19 -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 +23 -10
- 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} +115 -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,726 @@
|
|
|
1
|
+
# Configuration Structure
|
|
2
|
+
|
|
3
|
+
The `InteractConfig` object is the heart of `@wix/interact`. This guide explains how to organize and structure complex interactions efficiently.
|
|
4
|
+
|
|
5
|
+
## Basic Configuration Structure
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import type { InteractConfig } from '@wix/interact';
|
|
9
|
+
|
|
10
|
+
const config: InteractConfig = {
|
|
11
|
+
effects: {
|
|
12
|
+
// Reusable effect definitions
|
|
13
|
+
},
|
|
14
|
+
conditions: {
|
|
15
|
+
// Reusable condition definitions
|
|
16
|
+
},
|
|
17
|
+
interactions: [
|
|
18
|
+
// Array of interaction definitions
|
|
19
|
+
]
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Anatomy of an Interaction
|
|
24
|
+
|
|
25
|
+
Each interaction defines a complete cause-and-effect relationship:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
{
|
|
29
|
+
key: 'trigger-element', // What element triggers the interaction
|
|
30
|
+
selector: '.clickable-area', // Optional: Custom selector within source
|
|
31
|
+
trigger: 'hover', // What user action starts it
|
|
32
|
+
params: { // Optional trigger parameters
|
|
33
|
+
type: 'alternate'
|
|
34
|
+
},
|
|
35
|
+
conditions: ['desktop-only'], // Optional conditions to check
|
|
36
|
+
effects: [ // Array of effects to apply
|
|
37
|
+
{
|
|
38
|
+
key: 'animated-element',
|
|
39
|
+
selector: '.animation-target', // Optional: Custom selector within target
|
|
40
|
+
namedEffect: 'FadeIn',
|
|
41
|
+
duration: 300
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Element Selection with Selectors
|
|
48
|
+
|
|
49
|
+
The `selector` property allows you to specify exactly which element should be used for interactions, instead of being limited to the first child element.
|
|
50
|
+
|
|
51
|
+
### How Element Selection Works
|
|
52
|
+
|
|
53
|
+
Note that while `Interaction.key` defaults to `Effect.key` if it's missing, `selector` and `listContainer` are not inherited from the Interaction's config to the Effect's config.
|
|
54
|
+
|
|
55
|
+
The system follows this priority order for selecting elements:
|
|
56
|
+
|
|
57
|
+
1. **List Container** (if specified): `listContainer: '.item-list'`. Matches child elements of the selected container using `selector`, or all its immediate children if not specified.
|
|
58
|
+
2. **Custom Selector** (if specified): `selector: '.my-element'`.
|
|
59
|
+
3. **First Child** (fallback): The first child element of the interact-element.
|
|
60
|
+
|
|
61
|
+
### Basic Selector Usage
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const config: InteractConfig = {
|
|
65
|
+
interactions: [
|
|
66
|
+
{
|
|
67
|
+
key: 'card-container',
|
|
68
|
+
selector: '.card-image', // Select the image within the card
|
|
69
|
+
trigger: 'hover',
|
|
70
|
+
effects: [
|
|
71
|
+
{
|
|
72
|
+
key: 'card-container',
|
|
73
|
+
selector: '.card-overlay', // Select the overlay within the card
|
|
74
|
+
namedEffect: 'FadeIn',
|
|
75
|
+
duration: 300
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Selector vs ListContainer
|
|
84
|
+
|
|
85
|
+
- **`selector`**: Selects a single element using CSS selector
|
|
86
|
+
- **`listContainer`**: Selects a container for targeting its child elements for list-based interactions
|
|
87
|
+
- **Combined**: Use both to select elements within list items
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Using selector with listContainer
|
|
91
|
+
{
|
|
92
|
+
key: 'product-grid',
|
|
93
|
+
listContainer: '.product-item', // Each product item
|
|
94
|
+
selector: '.product-image', // Image within each item
|
|
95
|
+
trigger: 'hover',
|
|
96
|
+
effects: [
|
|
97
|
+
{
|
|
98
|
+
key: 'product-grid',
|
|
99
|
+
listContainer: '.product-item',
|
|
100
|
+
selector: '.product-overlay', // Overlay within each item
|
|
101
|
+
namedEffect: {
|
|
102
|
+
type: 'FadeIn'
|
|
103
|
+
},
|
|
104
|
+
duration: 200
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Organizing Simple Interactions
|
|
111
|
+
|
|
112
|
+
### Inline Effects (Small Projects)
|
|
113
|
+
For simple interactions, define effects directly:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const simpleConfig: InteractConfig = {
|
|
117
|
+
interactions: [
|
|
118
|
+
{
|
|
119
|
+
key: 'button-1',
|
|
120
|
+
trigger: 'hover',
|
|
121
|
+
effects: [
|
|
122
|
+
{
|
|
123
|
+
key: 'button-1',
|
|
124
|
+
namedEffect: {
|
|
125
|
+
type: 'Scale'
|
|
126
|
+
},
|
|
127
|
+
duration: 200,
|
|
128
|
+
easing: 'ease-out'
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
key: 'button-2',
|
|
134
|
+
trigger: 'click',
|
|
135
|
+
effects: [
|
|
136
|
+
{
|
|
137
|
+
key: 'modal',
|
|
138
|
+
keyframeEffect: {
|
|
139
|
+
name: 'scale-button',
|
|
140
|
+
keyframes: [
|
|
141
|
+
{ opacity: '0', transform: 'scale(0.9)' },
|
|
142
|
+
{ opacity: '1', transform: 'scale(1)' }
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
duration: 300
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Organizing Complex Interactions
|
|
154
|
+
|
|
155
|
+
### Reusable Effects
|
|
156
|
+
For larger projects, define effects separately and reference them:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const complexConfig: InteractConfig = {
|
|
160
|
+
effects: {
|
|
161
|
+
// Reusable effect definitions
|
|
162
|
+
'button-hover': {
|
|
163
|
+
keyframeEffect: {
|
|
164
|
+
name: 'button-hover',
|
|
165
|
+
keyframes: [
|
|
166
|
+
{ transform: 'scale(1)', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
|
|
167
|
+
{ transform: 'scale(1.05)', boxShadow: '0 8px 16px rgba(0,0,0,0.15)' }
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
duration: 200,
|
|
171
|
+
easing: 'ease-out'
|
|
172
|
+
},
|
|
173
|
+
'card-entrance': {
|
|
174
|
+
keyframeEffect: {
|
|
175
|
+
name: 'card-entrance',
|
|
176
|
+
keyframes: [
|
|
177
|
+
{ opacity: '0', transform: 'translateY(30px)' },
|
|
178
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
duration: 600,
|
|
182
|
+
easing: 'cubic-bezier(0.16, 1, 0.3, 1)'
|
|
183
|
+
},
|
|
184
|
+
'modal-open': {
|
|
185
|
+
keyframeEffect: {
|
|
186
|
+
name: 'modal-open',
|
|
187
|
+
keyframes: [
|
|
188
|
+
{ opacity: '0', transform: 'scale(0.95)' },
|
|
189
|
+
{ opacity: '1', transform: 'scale(1)' }
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
duration: 300,
|
|
193
|
+
easing: 'ease-out'
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
interactions: [
|
|
198
|
+
{
|
|
199
|
+
key: 'btn-primary',
|
|
200
|
+
trigger: 'hover',
|
|
201
|
+
effects: [
|
|
202
|
+
{
|
|
203
|
+
key: 'btn-primary',
|
|
204
|
+
effectId: 'button-hover' // Reference to reusable effect
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
key: 'product-card',
|
|
210
|
+
trigger: 'viewEnter',
|
|
211
|
+
params: { type: 'once', threshold: 0.3 },
|
|
212
|
+
effects: [
|
|
213
|
+
{
|
|
214
|
+
key: 'product-card',
|
|
215
|
+
effectId: 'card-entrance'
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
};
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Conditional Interactions
|
|
224
|
+
|
|
225
|
+
### Defining Conditions
|
|
226
|
+
Create reusable conditions for responsive design:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
const responsiveConfig: InteractConfig = {
|
|
230
|
+
conditions: {
|
|
231
|
+
'desktop-only': {
|
|
232
|
+
type: 'media',
|
|
233
|
+
predicate: '(min-width: 768px)'
|
|
234
|
+
},
|
|
235
|
+
'mobile-only': {
|
|
236
|
+
type: 'media',
|
|
237
|
+
predicate: '(max-width: 767px)'
|
|
238
|
+
},
|
|
239
|
+
'prefers-motion': {
|
|
240
|
+
type: 'media',
|
|
241
|
+
predicate: '(prefers-reduced-motion: no-preference)'
|
|
242
|
+
},
|
|
243
|
+
'large-container': {
|
|
244
|
+
type: 'container',
|
|
245
|
+
predicate: '(min-width: 600px)'
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
interactions: [
|
|
250
|
+
// Desktop hover effects
|
|
251
|
+
{
|
|
252
|
+
key: 'hero-image',
|
|
253
|
+
trigger: 'hover',
|
|
254
|
+
conditions: ['desktop-only', 'prefers-motion'],
|
|
255
|
+
effects: [
|
|
256
|
+
{
|
|
257
|
+
key: 'hero-image',
|
|
258
|
+
namedEffect: {
|
|
259
|
+
type: 'Scale'
|
|
260
|
+
},
|
|
261
|
+
duration: 400
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// Mobile tap effects
|
|
267
|
+
{
|
|
268
|
+
key: 'hero-image',
|
|
269
|
+
trigger: 'click',
|
|
270
|
+
conditions: ['mobile-only'],
|
|
271
|
+
effects: [
|
|
272
|
+
{
|
|
273
|
+
key: 'hero-image',
|
|
274
|
+
namedEffect: {
|
|
275
|
+
type: 'Pulse'
|
|
276
|
+
},
|
|
277
|
+
duration: 300
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Using Conditions in Effects
|
|
286
|
+
Apply conditions at the effect level:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
{
|
|
290
|
+
key: 'animated-section',
|
|
291
|
+
trigger: 'viewEnter',
|
|
292
|
+
effects: [
|
|
293
|
+
// Basic fade for all devices
|
|
294
|
+
{
|
|
295
|
+
key: 'animated-section',
|
|
296
|
+
namedEffect: {
|
|
297
|
+
type: 'FadeIn'
|
|
298
|
+
},
|
|
299
|
+
duration: 600
|
|
300
|
+
},
|
|
301
|
+
// Enhanced animation only on desktop
|
|
302
|
+
{
|
|
303
|
+
key: 'animated-section',
|
|
304
|
+
selector: ' .particles',
|
|
305
|
+
namedEffect: {
|
|
306
|
+
type: 'SlideUp'
|
|
307
|
+
},
|
|
308
|
+
duration: 800,
|
|
309
|
+
delay: 200,
|
|
310
|
+
conditions: ['desktop-only', 'prefers-motion']
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Modular Configuration Patterns
|
|
317
|
+
|
|
318
|
+
### Feature-Based Organization
|
|
319
|
+
Organize by features or components:
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
// buttons.ts
|
|
323
|
+
export const buttonInteractions = [
|
|
324
|
+
{
|
|
325
|
+
key: 'btn-primary',
|
|
326
|
+
trigger: 'hover',
|
|
327
|
+
effects: [{ key: 'btn-primary', effectId: 'button-hover' }]
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
key: 'btn-secondary',
|
|
331
|
+
trigger: 'hover',
|
|
332
|
+
effects: [{ key: 'btn-secondary', effectId: 'button-hover-secondary' }]
|
|
333
|
+
}
|
|
334
|
+
];
|
|
335
|
+
|
|
336
|
+
// cards.ts
|
|
337
|
+
export const cardInteractions = [
|
|
338
|
+
{
|
|
339
|
+
key: 'card',
|
|
340
|
+
trigger: 'viewEnter',
|
|
341
|
+
params: { type: 'once' },
|
|
342
|
+
effects: [{ key: 'card', effectId: 'card-entrance' }]
|
|
343
|
+
}
|
|
344
|
+
];
|
|
345
|
+
|
|
346
|
+
// main.ts
|
|
347
|
+
import { buttonInteractions } from './buttons';
|
|
348
|
+
import { cardInteractions } from './cards';
|
|
349
|
+
import { commonEffects } from './effects';
|
|
350
|
+
import { mediaConditions } from './conditions';
|
|
351
|
+
|
|
352
|
+
const config: InteractConfig = {
|
|
353
|
+
effects: commonEffects,
|
|
354
|
+
conditions: mediaConditions,
|
|
355
|
+
interactions: [
|
|
356
|
+
...buttonInteractions,
|
|
357
|
+
...cardInteractions
|
|
358
|
+
]
|
|
359
|
+
};
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Component-Specific Configurations
|
|
363
|
+
Create configurations for specific components:
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// NavbarConfig.ts
|
|
367
|
+
export const createNavbarConfig = (navbarId: string): InteractConfig => ({
|
|
368
|
+
effects: {
|
|
369
|
+
'nav-slide': {
|
|
370
|
+
keyframeEffect: {
|
|
371
|
+
name: 'nav-slide',
|
|
372
|
+
keyframes: [
|
|
373
|
+
{ transform: 'translateY(-100%)' },
|
|
374
|
+
{ transform: 'translateY(0)' }
|
|
375
|
+
]
|
|
376
|
+
},
|
|
377
|
+
duration: 300,
|
|
378
|
+
easing: 'ease-out'
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
interactions: [
|
|
382
|
+
{
|
|
383
|
+
key: navbarId,
|
|
384
|
+
selector: '.nav-toggle',
|
|
385
|
+
trigger: 'click',
|
|
386
|
+
effects: [
|
|
387
|
+
{
|
|
388
|
+
key: navbarId,
|
|
389
|
+
selector: '.nav-menu',
|
|
390
|
+
effectId: 'nav-slide'
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
]
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Usage
|
|
398
|
+
const navConfig = createNavbarConfig('main-nav');
|
|
399
|
+
Interact.create(navConfig);
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## Advanced Configuration Patterns
|
|
403
|
+
|
|
404
|
+
TBD
|
|
405
|
+
|
|
406
|
+
## Performance Considerations
|
|
407
|
+
|
|
408
|
+
### Lazy Loading Configurations
|
|
409
|
+
Load configurations on demand:
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
const loadFeatureConfig = async (featureName: string): Promise<InteractConfig> => {
|
|
413
|
+
const module = await import(`./features/${featureName}/interactions.js`);
|
|
414
|
+
return module.default;
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// Usage
|
|
418
|
+
const heroConfig = await loadFeatureConfig('hero');
|
|
419
|
+
Interact.create(heroConfig);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## Real-World Example: E-commerce Product Page
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
const productPageConfig: InteractConfig = {
|
|
426
|
+
effects: {
|
|
427
|
+
'product-image-zoom': {
|
|
428
|
+
keyframeEffect: {
|
|
429
|
+
name: 'product-image-zoom',
|
|
430
|
+
keyframes: [
|
|
431
|
+
{ transform: 'scale(1)' },
|
|
432
|
+
{ transform: 'scale(1.1)' }
|
|
433
|
+
]
|
|
434
|
+
},
|
|
435
|
+
duration: 300,
|
|
436
|
+
easing: 'ease-out'
|
|
437
|
+
},
|
|
438
|
+
'add-to-cart-success': {
|
|
439
|
+
keyframeEffect: {
|
|
440
|
+
name: 'add-to-cart-success',
|
|
441
|
+
keyframes: [
|
|
442
|
+
{ backgroundColor: '#ef4444', transform: 'scale(1)' },
|
|
443
|
+
{ transform: 'scale(1.05)' },
|
|
444
|
+
{ backgroundColor: '#10b981', transform: 'scale(1)' }
|
|
445
|
+
]
|
|
446
|
+
},
|
|
447
|
+
duration: 600,
|
|
448
|
+
easing: 'ease-in-out'
|
|
449
|
+
},
|
|
450
|
+
'review-entrance': {
|
|
451
|
+
keyframeEffect: {
|
|
452
|
+
name: 'review-entrance',
|
|
453
|
+
keyframes: [
|
|
454
|
+
{ opacity: '0', transform: 'translateY(20px)' },
|
|
455
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
456
|
+
]
|
|
457
|
+
},
|
|
458
|
+
duration: 500,
|
|
459
|
+
easing: 'ease-out'
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
conditions: {
|
|
464
|
+
'desktop': {
|
|
465
|
+
type: 'media',
|
|
466
|
+
predicate: '(min-width: 1024px)'
|
|
467
|
+
},
|
|
468
|
+
'touch-device': {
|
|
469
|
+
type: 'media',
|
|
470
|
+
predicate: '(hover: none)'
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
interactions: [
|
|
475
|
+
// Product image hover (desktop only)
|
|
476
|
+
{
|
|
477
|
+
key: 'product-image',
|
|
478
|
+
trigger: 'hover',
|
|
479
|
+
conditions: ['desktop'],
|
|
480
|
+
effects: [
|
|
481
|
+
{
|
|
482
|
+
key: 'product-image',
|
|
483
|
+
selector: 'img',
|
|
484
|
+
effectId: 'product-image-zoom'
|
|
485
|
+
}
|
|
486
|
+
]
|
|
487
|
+
},
|
|
488
|
+
|
|
489
|
+
// Add to cart success animation
|
|
490
|
+
{
|
|
491
|
+
key: 'add-to-cart-btn',
|
|
492
|
+
trigger: 'click',
|
|
493
|
+
effects: [
|
|
494
|
+
{
|
|
495
|
+
key: 'add-to-cart-btn',
|
|
496
|
+
effectId: 'add-to-cart-success'
|
|
497
|
+
}
|
|
498
|
+
]
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
// Staggered review animations
|
|
502
|
+
{
|
|
503
|
+
key: 'review-1',
|
|
504
|
+
trigger: 'viewEnter',
|
|
505
|
+
params: { type: 'once', threshold: 0.2 },
|
|
506
|
+
effects: [
|
|
507
|
+
{
|
|
508
|
+
key: 'review-1',
|
|
509
|
+
effectId: 'review-entrance',
|
|
510
|
+
delay: 0
|
|
511
|
+
}
|
|
512
|
+
]
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
key: 'review-2',
|
|
516
|
+
trigger: 'viewEnter',
|
|
517
|
+
params: { type: 'once', threshold: 0.2 },
|
|
518
|
+
effects: [
|
|
519
|
+
{
|
|
520
|
+
key: 'review-2',
|
|
521
|
+
effectId: 'review-entrance',
|
|
522
|
+
delay: 100
|
|
523
|
+
}
|
|
524
|
+
]
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
};
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
## Advanced Selector Examples
|
|
531
|
+
|
|
532
|
+
### Card Component with Multiple Interactive Areas
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
const cardConfig: InteractConfig = {
|
|
536
|
+
effects: {
|
|
537
|
+
'card-lift': {
|
|
538
|
+
keyframeEffect: {
|
|
539
|
+
name: 'card-lift',
|
|
540
|
+
keyframes: [
|
|
541
|
+
{ transform: 'translateY(0px)', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
|
|
542
|
+
{ transform: 'translateY(-4px)', boxShadow: '0 8px 16px rgba(0,0,0,0.15)' }
|
|
543
|
+
]
|
|
544
|
+
},
|
|
545
|
+
duration: 200,
|
|
546
|
+
easing: 'ease-out'
|
|
547
|
+
},
|
|
548
|
+
'image-zoom': {
|
|
549
|
+
keyframeEffect: {
|
|
550
|
+
name: 'image-zoom',
|
|
551
|
+
keyframes: [
|
|
552
|
+
{ transform: 'scale(1)' },
|
|
553
|
+
{ transform: 'scale(1.05)' }
|
|
554
|
+
]
|
|
555
|
+
},
|
|
556
|
+
duration: 300,
|
|
557
|
+
easing: 'ease-out'
|
|
558
|
+
},
|
|
559
|
+
'button-pulse': {
|
|
560
|
+
keyframeEffect: {
|
|
561
|
+
name: 'button-pulse',
|
|
562
|
+
keyframes: [
|
|
563
|
+
{ transform: 'scale(1)' },
|
|
564
|
+
{ transform: 'scale(1.1)' },
|
|
565
|
+
{ transform: 'scale(1)' }
|
|
566
|
+
]
|
|
567
|
+
},
|
|
568
|
+
duration: 400,
|
|
569
|
+
easing: 'ease-in-out'
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
interactions: [
|
|
574
|
+
// Hover on card image triggers card lift
|
|
575
|
+
{
|
|
576
|
+
key: 'product-card',
|
|
577
|
+
selector: '.card-image', // Trigger area: just the image
|
|
578
|
+
trigger: 'hover',
|
|
579
|
+
effects: [
|
|
580
|
+
{
|
|
581
|
+
key: 'product-card',
|
|
582
|
+
selector: '.card-container', // Effect target: entire card
|
|
583
|
+
effectId: 'card-lift'
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
key: 'product-card',
|
|
587
|
+
selector: '.card-image img', // Effect target: image itself
|
|
588
|
+
effectId: 'image-zoom'
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
|
|
593
|
+
// Click on CTA button
|
|
594
|
+
{
|
|
595
|
+
key: 'product-card',
|
|
596
|
+
selector: '.cta-button', // Trigger area: CTA button
|
|
597
|
+
trigger: 'click',
|
|
598
|
+
effects: [
|
|
599
|
+
{
|
|
600
|
+
key: 'product-card',
|
|
601
|
+
selector: '.cta-button', // Effect target: button itself
|
|
602
|
+
effectId: 'button-pulse'
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
}
|
|
606
|
+
]
|
|
607
|
+
};
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### Navigation Menu with Nested Selectors
|
|
611
|
+
|
|
612
|
+
```typescript
|
|
613
|
+
const navConfig: InteractConfig = {
|
|
614
|
+
effects: {
|
|
615
|
+
'dropdown-slide': {
|
|
616
|
+
keyframeEffect: {
|
|
617
|
+
name: 'dropdown-slide',
|
|
618
|
+
keyframes: [
|
|
619
|
+
{ opacity: '0', transform: 'translateY(-10px)' },
|
|
620
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
621
|
+
]
|
|
622
|
+
},
|
|
623
|
+
duration: 250,
|
|
624
|
+
easing: 'ease-out'
|
|
625
|
+
},
|
|
626
|
+
'menu-item-highlight': {
|
|
627
|
+
keyframeEffect: {
|
|
628
|
+
name: 'menu-item-highlight',
|
|
629
|
+
keyframes: [
|
|
630
|
+
{ backgroundColor: 'transparent' },
|
|
631
|
+
{ backgroundColor: 'rgba(0, 123, 255, 0.1)' }
|
|
632
|
+
]
|
|
633
|
+
},
|
|
634
|
+
duration: 150,
|
|
635
|
+
easing: 'ease-out'
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
|
|
639
|
+
interactions: [
|
|
640
|
+
// Hover on main menu items
|
|
641
|
+
{
|
|
642
|
+
key: 'main-nav',
|
|
643
|
+
listContainer: 'nav',
|
|
644
|
+
selector: '.nav-item[data-has-dropdown]', // Only items with dropdowns
|
|
645
|
+
trigger: 'hover',
|
|
646
|
+
effects: [
|
|
647
|
+
{
|
|
648
|
+
key: 'main-nav',
|
|
649
|
+
listContainer: 'nav',
|
|
650
|
+
selector: '.nav-item[data-has-dropdown] .dropdown-menu',
|
|
651
|
+
effectId: 'dropdown-slide'
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
key: 'main-nav',
|
|
655
|
+
listContainer: 'nav',
|
|
656
|
+
selector: '.nav-item[data-has-dropdown]',
|
|
657
|
+
effectId: 'menu-item-highlight'
|
|
658
|
+
}
|
|
659
|
+
]
|
|
660
|
+
}
|
|
661
|
+
]
|
|
662
|
+
};
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
### Gallery with Dynamic Item Selection
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
const galleryConfig: InteractConfig = {
|
|
669
|
+
effects: {
|
|
670
|
+
'image-overlay': {
|
|
671
|
+
keyframeEffect: {
|
|
672
|
+
name: 'image-overlay',
|
|
673
|
+
keyframes: [
|
|
674
|
+
{ opacity: '0' },
|
|
675
|
+
{ opacity: '1' }
|
|
676
|
+
]
|
|
677
|
+
},
|
|
678
|
+
duration: 300,
|
|
679
|
+
easing: 'ease-in-out'
|
|
680
|
+
}
|
|
681
|
+
},
|
|
682
|
+
|
|
683
|
+
interactions: [
|
|
684
|
+
// Gallery items with list container and selector
|
|
685
|
+
{
|
|
686
|
+
key: 'image-gallery',
|
|
687
|
+
listContainer: '.gallery-grid', // Container with multiple items
|
|
688
|
+
selector: '.gallery-item img', // Image within each item
|
|
689
|
+
trigger: 'hover',
|
|
690
|
+
effects: [
|
|
691
|
+
{
|
|
692
|
+
key: 'image-gallery',
|
|
693
|
+
listContainer: '.gallery-grid',
|
|
694
|
+
selector: '.gallery-item .overlay', // Overlay within each item
|
|
695
|
+
effectId: 'image-overlay'
|
|
696
|
+
}
|
|
697
|
+
]
|
|
698
|
+
}
|
|
699
|
+
]
|
|
700
|
+
};
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
## Best Practices
|
|
704
|
+
|
|
705
|
+
### Configuration Organization
|
|
706
|
+
1. **Start simple** - Use inline effects for prototypes
|
|
707
|
+
2. **Extract reusable effects** as your project grows
|
|
708
|
+
3. **Group by feature** rather than by type
|
|
709
|
+
|
|
710
|
+
### Accessibility
|
|
711
|
+
1. **Use `activate` instead of `click`** for keyboard accessibility (Enter/Space)
|
|
712
|
+
2. **Use `interest` instead of `hover`** for keyboard accessibility (Focus)
|
|
713
|
+
3. **Or enable `allowA11yTriggers` globally** to make existing triggers accessible
|
|
714
|
+
|
|
715
|
+
### Performance Tips
|
|
716
|
+
1. **Reuse effects** instead of duplicating them
|
|
717
|
+
2. **Use conditions** to avoid unnecessary animations
|
|
718
|
+
3. **Lazy load** configurations for large applications
|
|
719
|
+
4. **Validate in development** to catch errors early
|
|
720
|
+
|
|
721
|
+
## Next Steps
|
|
722
|
+
|
|
723
|
+
Now that you understand configuration structure:
|
|
724
|
+
- **[Custom Elements](./custom-elements.md)** - Learn about `<interact-element>`
|
|
725
|
+
- **[State Management](./state-management.md)** - Advanced state handling
|
|
726
|
+
- **[Conditions and Media Queries](./conditions-and-media-queries.md)** - Responsive interactions
|