You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- New `GestureRegion` component for wrapping gesture sensitive components. React Motion Router will ignore navigation gestures that overlap these regions.
4
+
5
+
## Enhancements
6
+
- Added React Motion Router events to the global event listeners interface. Meaning now you get code completion when writing any of these event handlers:
7
+
-`page-animation-start`
8
+
-`page-animation-end`
9
+
-`motion-progress-start`
10
+
-`motion-progress`
11
+
-`motion-progress-end`
12
+
- Fallback components now have access to route parameters just like the actual component.
13
+
14
+
## Bug Fixes
15
+
- Fixed a bug that made navigation impossible after a gesture navigation when browser routing is enabled.
Copy file name to clipboardExpand all lines: README.md
+81-31Lines changed: 81 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@
6
6
React Motion Router
7
7
</h1>
8
8
9
-
Declarative routing library for React ⚛ with page transitions and animations 🚀. Under Development 🧪. Based on React Router and React Navigation.
9
+
Declarative routing library for React ⚛ with 60FPS page transitions and animations 🚀. Out of the box support for Shared Element Transitions 🤩. Under Development 🧪. Based on React Router and React Navigation.
10
10
11
11
#### [Demo](https://router.nxtetechnologies.com)
12
12
@@ -45,7 +45,7 @@ npm install react-motion-router
45
45
Use the `Router` component to render your screens. Pass a React component to the component prop of `Stack.Screen` to be rendered when the path prop of the screen has been navigated to.
46
46
47
47
```
48
-
...
48
+
// ...
49
49
import {Router, Stack} from 'react-motion-router';
50
50
51
51
function Home() {
@@ -58,41 +58,56 @@ function Home() {
58
58
function App() {
59
59
return(
60
60
<div className="app">
61
-
<Stack.Screen path="/" component={Home} />
61
+
<Router>
62
+
<Stack.Screen path="/" component={Home} />
63
+
</Router>
62
64
</div>
63
65
):
64
66
}
65
67
66
-
...
68
+
// ...
67
69
```
68
70
71
+
You can also pass lazy loaded components to the screen along with an optional fallback component to be rendered while your component loads.
72
+
73
+
```
74
+
// ...
75
+
const Home = React.lazy(() => import('./Screens/Home'));
If a fallback component is provided the fallback component is animated in just like the actual component would and is even able to do gesture navigation all while your screen is loaded in asynchronously.
83
+
69
84
#### Navigation
70
85
71
86
Navigation is done through the navigation object exposed on your screen's props.
72
87
73
88
```
74
-
...
89
+
// ...
75
90
function Home(props) {
76
91
return(
77
92
<div>
78
-
...
93
+
// ...
79
94
<button onClick={() => {
80
95
props.navigation.goBack();
81
96
}}>BACK</button>
82
97
<button
83
98
onClick={() => {
84
99
props.navigation.navigate('/posts');
85
100
}}>Posts</button>
86
-
...
101
+
// ...
87
102
</div>
88
103
);
89
104
}
90
-
...
105
+
// ...
91
106
```
92
107
93
108
The navigation object also exposes information such as `navigation.location`. It's the same as `window.location` but it will always be up to date and correct regardless of if browser routing has been disabled.
94
109
95
-
#### Passing Parameters to Other Screens
110
+
#### Passing Parameters to Screens
96
111
97
112
To pass data to the next screen, pass a value to the navigate function.
98
113
@@ -108,30 +123,59 @@ To access this data on the next screen:
108
123
109
124
```
110
125
// Screen: POSTS
111
-
...
126
+
// ...
112
127
<h1>{props.route.params.post.title}</h1>
113
-
...
128
+
// ...
114
129
```
115
130
116
131
All data passed to the navigate function is accessible on the target screen through the route prop.
117
132
133
+
Parameters can also be parsed from URL parameters for example a pathname with a search part such as `/slides?hero=0` will be parsed into an object with key `hero` and value `0`. To customise this behaviour you can pass a custom deserialiser or serialiser function to the `Router` component which will be used to convert between URL parameters and React Motion Router parameters and vice-versa.
134
+
135
+
```
136
+
<Router
137
+
config={{
138
+
paramsSerialiser: (params) => {
139
+
const searchPart = new URLSearchParams(params).toString()
140
+
141
+
return btoa(searchPart); // search encoded as Base64 string
142
+
},
143
+
paramsDeserialiser: (b64SearchPart) => {
144
+
const searchPart = atob(b64SearchPart.slice(1)); // start after the ?
145
+
const searchParams = new URLSearchParams(searchPart);
146
+
147
+
const params = {};
148
+
for (let [key, value] of searchParams) {
149
+
params[key] = value;
150
+
}
151
+
152
+
return params;
153
+
}
154
+
}}
155
+
>
156
+
// ...
157
+
</Router>
158
+
```
159
+
160
+
In this example `/slides?hero=0` becomes `/slides?aGVybz0w`.
161
+
118
162
#### Default Parameters
119
163
120
164
A default parameter can be passed to the screen by passing a value to the defaultParams prop on `Stack.Screen` component.
Transitions are a feature baked into react-motion-router; hence the name... To transition between pages do:
178
+
Transitions are a feature baked into react-motion-router; hence the name... To transition between screens do:
135
179
136
180
```
137
181
<Router config={{
@@ -141,7 +185,7 @@ Transitions are a feature baked into react-motion-router; hence the name... To t
141
185
duration: 300
142
186
}
143
187
}}>
144
-
...
188
+
// ...
145
189
</Router>
146
190
```
147
191
@@ -150,7 +194,7 @@ You can subscribe to the transition progress by using the motion consumer compon
150
194
```
151
195
import {Motion} from 'react-motion-router';
152
196
153
-
...
197
+
// ...
154
198
<Motion.Consumer>
155
199
{(progress) => {
156
200
return (
@@ -164,30 +208,30 @@ import {Motion} from 'react-motion-router';
164
208
static contextType = Motion;
165
209
```
166
210
167
-
The progress is updated as the animation plays and can be used to update DOM style attributes or control playback of an animation.
211
+
The progress is updated as the animation plays and can be used to interpolate DOM style attributes or control playback of an animation.
168
212
169
213
#### Shared Element Transition
170
214
171
215
To do a shared element transition wrap the component you would like shared between screens and supply it with a unique ID prop.
172
216
173
217
```
174
218
// Screen: HOME
175
-
...
219
+
// ...
176
220
<SharedElement id="post">
177
221
<h1>Post</h1>
178
222
</SharedElement>
179
-
...
223
+
// ...
180
224
```
181
225
182
226
and on another screen:
183
227
184
228
```
185
229
Screen: POSTS
186
-
...
230
+
// ...
187
231
<SharedElement id="post">
188
232
<h1>Post</h1>
189
233
</SharedElement>
190
-
...
234
+
// ...
191
235
```
192
236
193
237
That's it! The element will transition from one screen to the next seemlessly. They can even do layered animations.
@@ -205,18 +249,19 @@ That's it! The element will transition from one screen to the next seemlessly. T
205
249
</SharedElement>
206
250
```
207
251
208
-
This way the X and Y axis are animated independently and can alter the path of the shared element while transitioning.
252
+
This way the X and Y axis are animated independently and can alter the path of the shared element while transitioning. Note that these durations are clamped to the overall router transition duration.
| component | JSXElementConstructor | A valid React Component or React lazy loaded Component to be rendered. |
262
+
| fallback | ReactNode | A valid React Node to be rendered while the real component is suspended (lazy loading). |
263
+
| defaultParams | Object | A dictionary of parameters that can be accessed by the rendered component. |
264
+
| config | Object | A dictionary of options to alter the behaviour of the screen. |
220
265
221
266
#### Stack.Screen Config
222
267
@@ -235,6 +280,8 @@ This way the X and Y axis are animated independently and can alter the path of t
235
280
| swipeAreaWidth | number | Area in pixels from the left edge of the screen that gesture navigation can be triggered from. |
236
281
| hysteresis | number | Percent from 0-100 which specifies minimum gesture progress before navigation is triggered. |
237
282
| minFlingVelocity | number | Minimum average velocity of swipe gesture before navigation is triggered even if hysteresis was not reached. |
283
+
| paramsDeserialiser | Function | A function that takes a URL search part string as input and outputs a valid JavaScript object. |
284
+
| paramsSerialiser | Function | A function that takes a valid JavaScript object as input and outputs a URL search part string. |
238
285
239
286
#### AnimationConfig
240
287
@@ -264,20 +311,23 @@ This way the X and Y axis are animated independently and can alter the path of t
264
311
It is useful to note that the duration and easing function properties can also be set on the X and Y axis as independent values by specifying an X or Y property on the shared element config object.
265
312
266
313
```
267
-
...
314
+
// ...
268
315
config={{
269
316
x: {
270
317
easingFunction: "ease-in-out",
271
318
duration: 500
272
319
}
273
320
}}
274
-
...
321
+
// ...
275
322
```
276
323
277
324
## Remarks
278
325
279
326
This is a work in progress and elements of this solution are subject to change.
280
-
There are a few limitations to be aware of for example there is no analogue for HashRouter in this solution.
327
+
There are a few limitations to be aware of for example there is:
328
+
329
+
- no analogue for HashRouter in this solution
330
+
- no nested routing although there are plans to add this eventually.
0 commit comments