{"id":13880816,"url":"https://github.com/absurdprofit/react-motion-router","last_synced_at":"2025-04-10T19:40:33.007Z","repository":{"id":40481693,"uuid":"439216850","full_name":"absurdprofit/react-motion-router","owner":"absurdprofit","description":"Declarative routing library for React ⚛ with page transitions and animations out of the box. Under Development 🧪.","archived":false,"fork":false,"pushed_at":"2024-08-01T07:59:37.000Z","size":23322,"stargazers_count":149,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-08-01T08:36:50.165Z","etag":null,"topics":["animation","history","navigation","react","route","router","routing","shared-element","shared-element-transition","transition"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/absurdprofit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-17T05:08:00.000Z","updated_at":"2024-08-01T08:36:59.759Z","dependencies_parsed_at":"2023-01-21T04:51:46.500Z","dependency_job_id":"4ad9a497-23fd-48b0-886b-bae70748f53a","html_url":"https://github.com/absurdprofit/react-motion-router","commit_stats":{"total_commits":172,"total_committers":2,"mean_commits":86.0,"dds":"0.046511627906976716","last_synced_commit":"8614020d5d8bfb71f706638133121c8e68e3785e"},"previous_names":["absurdprofit/react-motion-router","nxtexe/react-motion-router"],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/absurdprofit%2Freact-motion-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/absurdprofit%2Freact-motion-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/absurdprofit%2Freact-motion-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/absurdprofit%2Freact-motion-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/absurdprofit","download_url":"https://codeload.github.com/absurdprofit/react-motion-router/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248281419,"owners_count":21077423,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","history","navigation","react","route","router","routing","shared-element","shared-element-transition","transition"],"created_at":"2024-08-06T08:03:30.754Z","updated_at":"2025-04-10T19:40:32.982Z","avatar_url":"https://github.com/absurdprofit.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"logo.png\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n    React Motion Router\n\u003c/h1\u003e\n\nDeclarative 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.\n\n#### [Demo](https://router.nxtetechnologies.com)\n\n# [![version](https://img.shields.io/npm/v/react-motion-router)](https://www.npmjs.com/package/react-motion-router) [![downloads](https://img.shields.io/npm/dm/react-motion-router)](https://www.npmjs.com/package/react-motion-router) [![license](https://img.shields.io/npm/l/react-motion-router)](https://github.com/nxtexe/react-motion-router/blob/main/LICENSE)\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Basic](#basic)\n  - [Navigation](#navigation)\n  - [Passing Params](#passing-parameters-to-screens)\n  - [Default Params](#default-parameters)\n  - [Transitions](#transitions)\n  - [Shared Element Transition](#shared-element-transition)\n- [API Documentation](#api-documentation)\n  - [Stack.Screen](#stackscreen)\n  - [Stack.Screen Config](#stackscreen-config)\n  - [Router Config](#router-config)\n  - [AnimationConfig](#animationconfig)\n  - [SharedElement](#sharedelement)\n  - [SharedElement Config](#sharedelement-config)\n- [Remarks](#remarks)\n- [Credits](#credits)\n\n## Installation\n\n```\nnpm install react-motion-router\n```\n\n## Usage\n\n#### Basic\n\nUse 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.\n\n```\n// ...\nimport {Router, Stack} from 'react-motion-router';\n\nfunction Home() {\n    return(\n        \u003cdiv className=\"Home\"\u003e\n            \u003ch1\u003eHello World\u003c/h1\u003e\n        \u003c/div\u003e\n    );\n}\nfunction App() {\n    return(\n        \u003cdiv className=\"app\"\u003e\n            \u003cRouter\u003e\n                \u003cStack.Screen path=\"/\" component={Home} /\u003e\n            \u003c/Router\u003e\n        \u003c/div\u003e\n    ):\n}\n\n// ...\n```\n\nYou can also pass lazy loaded components to the screen along with an optional fallback component to be rendered while your component loads.\n\n```\n// ...\nconst Home = React.lazy(() =\u003e import('./Screens/Home'));\n\u003cRouter\u003e\n    \u003cStack.Screen path=\"/\" component={Home} fallback={\u003cdiv className='screen-fallback home'\u003e\u003c/div\u003e}\u003e\n\u003c/Router\u003e\n// ...\n```\n\nIf 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.\n\n#### Navigation\n\nNavigation is done through the navigation object exposed on your screen's props.\n\n```\n// ...\nfunction Home(props) {\n    return(\n        \u003cdiv\u003e\n            // ...\n            \u003cbutton onClick={() =\u003e {\n                props.navigation.goBack();\n            }}\u003eBACK\u003c/button\u003e\n            \u003cbutton\n                onClick={() =\u003e {\n                    props.navigation.navigate('/posts');\n                }}\u003ePosts\u003c/button\u003e\n            // ...\n        \u003c/div\u003e\n    );\n}\n// ...\n```\nOR for a more declarative approach opt for the `Anchor` compoennt\n```\n\u003cAnchor href=\"/posts\"\u003ePosts\u003c/Anchor\u003e\n```\n\nThe 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.\n\n#### Passing Parameters to Screens\n\nTo pass data to the next screen, pass a value to the navigate function.\n\n```\nprops.navigation.navigate('/posts', {\n    post: {\n        title: \"Post\"\n    }\n});\n\n// Or with Anchor component\n\u003cAnchor href=\"/posts\" params={{\n    post: {\n        title: \"Post\"\n    }\n}}\u003ePosts\u003c/Anchor\u003e // For cross domain URLs the params are appended as search parameters.\n```\n\nTo access this data on the next screen:\n\n```\n// Screen: POSTS\n// ...\n\u003ch1\u003e{props.route.params.post.title}\u003c/h1\u003e\n// ...\n```\n\nAll data passed to the navigate function is accessible on the target screen through the route prop.\n\nParameters 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 deserializer or serializer function to the `Router` component which will be used to convert between URL parameters and React Motion Router parameters and vice-versa.\n\n```\n\u003cRouter\n    config={{\n        paramsSerializer: (params) =\u003e {\n            const searchPart = new URLSearchParams(params).toString()\n\n            return btoa(searchPart); // search encoded as Base64 string\n        },\n        paramsDeserializer: (b64SearchPart) =\u003e {\n            const searchPart = atob(b64SearchPart.slice(1)); // start after the ?\n            const searchParams = new URLSearchParams(searchPart);\n\n            const params = {};\n            for (let [key, value] of searchParams) {\n                params[key] = value;\n            }\n\n            return params;\n        }\n    }}\n\u003e\n// ...\n\u003c/Router\u003e\n```\n\nIn this example `/slides?hero=0` becomes `/slides?aGVybz0w`.\n\n#### Default Parameters\n\nA default parameter can be passed to the screen by passing a value to the defaultParams prop on `Stack.Screen` component.\n\n```\n// ...\n\u003cStack.Screen path=\"/posts\" component={Posts} defaultParams={{\n    post: {\n        title: \"Default Title\"\n    }\n}}/\u003e\n// ...\n```\n\n#### Transitions\n\nTransitions are a feature baked into react-motion-router; hence the name... To transition between screens do:\n\n```\n\u003cRouter config={{\n    animation: {\n        type: \"slide\",\n        direction: \"right\",\n        duration: 300\n    }\n}}\u003e\n// ...\n\u003c/Router\u003e\n```\nYou can provide custom keyframes and options to customise and extend the types of animations available.\n```\n\u003cRouter config={{\n    animation: {\n        in: {\n            keyframes: [{opacity: 0}, {opacity: 1}],\n            options: {\n                duration: 350,\n                easing: 'ease'\n            }\n        },\n        out: {\n            keyframes: [{opacity: 1}, {opacity: 0}],\n            options: {\n                duration: 350,\n                easing: 'ease-out'\n            }\n        }\n    }\n}}\u003e\n// ...\n\u003c/Router\u003e\n```\n\nYou can subscribe to the transition progress by using the motion consumer component.\n\n```\nimport {Motion} from 'react-motion-router';\n\n// ...\n\u003cMotion.Consumer\u003e\n    {(progress) =\u003e {\n        return (\n            \u003cdiv\u003e{progress}\u003c/div\u003e\n        );\n    }}\n\u003c/Motion.Consumer\u003e\n\n// OR Class.contextType\n\nstatic contextType = Motion;\n```\n\nThe progress is updated as the animation plays and can be used to interpolate DOM style attributes or control playback of an animation.\n\n#### Shared Element Transition\n\nTo do a shared element transition wrap the component you would like shared between screens and supply it with a unique ID prop.\n\n```\n// Screen: HOME\n// ...\n\u003cSharedElement id=\"post\"\u003e\n    \u003ch1\u003ePost\u003c/h1\u003e\n\u003c/SharedElement\u003e\n// ...\n```\n\nand on another screen:\n\n```\nScreen: POSTS\n// ...\n\u003cSharedElement id=\"post\"\u003e\n    \u003ch1\u003ePost\u003c/h1\u003e\n\u003c/SharedElement\u003e\n// ...\n```\n\nThat's it! The element will transition from one screen to the next seemlessly. They can even do layered animations.\n\n```\n\u003cSharedELement id=\"post\" config={{\n    x: {\n        duration: 100\n    },\n    y: {\n        duration: 300\n    }\n}}\u003e\n    \u003ch1\u003ePost\u003c/h1\u003e\n\u003c/SharedElement\u003e\n```\n\nThis 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.\n\n## API Documentation\n\n#### Stack.Screen\n\n| Prop          | Type                  | Description                                                                             |\n| ------------- | --------------------- | --------------------------------------------------------------------------------------- |\n| path          | string                | Pathname of the screen.                                                                 |\n| component     | JSXElementConstructor | A valid React Component or React lazy loaded Component to be rendered.                  |\n| fallback      | ReactNode             | A valid React Node to be rendered while the real component is suspended (lazy loading). |\n| defaultParams | Object                | A dictionary of parameters that can be accessed by the rendered component.              |\n| config        | Object                | A dictionary of options to alter the behaviour of the screen.                           |\n\n#### Stack.Screen Config\n\n| Property  | Type                                      | Description                                                                                                                                                                                            |\n| --------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| animation | AnimationConfig or AnimationConfigFactory | AnimationConfig object or function that returns an AnimationConfig object. This config object is used to modify the router's transition behaviour. In and out animation can also be set independently. |\n| disableDiscovery      | boolean         | Option to disable gesture navigation.                                                                                                                                       |\n| swipeAreaWidth        | number          | Area in pixels from the edge of the screen that gesture navigation can be triggered from.                                                                              |\n| hysteresis            | number          | Percent from 0-100 which specifies minimum gesture progress before navigation is triggered.                                                                                 |\n| minFlingVelocity      | number          | Minimum average velocity of swipe gesture before navigation is triggered even if hysteresis was not reached.                                                                |\n| keepAlive      | boolean          | If true the current screen will remain in the DOM tree after you navigate to another screen.                                                                |\n| swipeDirection      | \"left\", \"right\", \"up\" or \"down\"          | The direction to swipe in order to trigger a gesture navigation.                                                                |\n\n#### Router Config\n\n| Property              | Type            | Description                                                                                                                                                                 |\n| --------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| defaultRoute          | string          | If the user navigates directly to a route other than the default and navigate.goBack() is called the app will navigate to the default route instead of leaving the website. |\n| disableDiscovery      | boolean         | Option to disable gesture navigation.                                                                                                                                       |\n| disableBrowserRouting | boolean         | Option to avoid updating browser native history stack and rely completely on memory routing.                                                                                |\n| animation             | AnimationConfig | Config object used to modify the router's global transition behaviour. In and out animation can also be set independently.                                                  |\n| swipeAreaWidth        | number          | Area in pixels from the edge of the screen that gesture navigation can be triggered from.                                                                              |\n| hysteresis            | number          | Percent from 0-100 which specifies minimum gesture progress before navigation is triggered.                                                                                 |\n| minFlingVelocity      | number          | Minimum average velocity of swipe gesture before navigation is triggered even if hysteresis was not reached.                                                                |\n| swipeDirection      | \"left\", \"right\", \"up\" or \"down\"          | The direction to swipe in order to trigger a gesture navigation.                                                                |\n| paramsDeserializer    | Function        | A function that takes a URL search part string as input and outputs a valid JavaScript object.                                                                              |\n| paramsSerializer      | Function        | A function that takes a valid JavaScript object as input and outputs a URL search part string.                                                                              |\n\n#### AnimationConfig\n\n| Property  | Type                                         | Description                                                                                                                                                                            |\n| --------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| type      | \"slide\", \"fade\", \"zoom\" or \"none\"            | The animation type used for page transitions.                                                                                                                                          |\n| duration  | number                                       | The time in milliseconds for how long page transitions are from start to end.                                                                                                          |\n| direction | \"left\", \"right\", \"up\", \"down\", \"in\" or \"out\" | The direction used for slide transitions. The direction is swapped automatically on back navigation. i.e. The user presses their browser back button or navigation.goBack() is called. |\n\n#### SharedElement\n\n| Prop     | Type             | Description                                                                                                                |\n| -------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| id       | string or number | The unique ID used to keep track of the element in the scene. The IDs must match in each screen for a transition to occur. |\n| children | React.ReactChild | A single React element which will be displayed between transitions.                                                        |\n| config   | Object           | Config object used to alter the behaviour of the shared element.                                                           |\n\n#### SharedElement Config\n\n| Property        | Type                                            | Description                                                                                                                                                                 |\n| --------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| type            | \"morph\", \"fade\", \"fade-through\" or \"cross-fade\" | Type of transition.                                                                                                                                                         |\n| transformOrigin | TransformOrigin                                 | Changes transform alignment of shared element.                                                                                                                              |\n| duration        | number                                          | The time in milliseconds for how long the shared element transition is from start to end                                                                                    |\n| easingFunction  | CSS \u0026lt;easing-function\u0026gt;                     | Denotes a mathematical function that describes the rate at which a numerical value changes.\u003csup\u003e[1](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function)\u003c/sup\u003e |\n\nIt 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.\n\n```\n// ...\nconfig={{\n    x: {\n        easingFunction: \"ease-in-out\",\n        duration: 500\n    }\n}}\n// ...\n```\n\n## Remarks\n\nThis is a work in progress and elements of this solution are subject to change.\nThere are a few limitations to be aware of for example there is:\n\n- no analogue for HashRouter in this solution.\n- no nested routing although there are plans to add this eventually.\n\n## Credits\n\nShoutout to [@IzjerenHein](https://github.com/IjzerenHein) whose [react-native-shared-element](https://github.com/IjzerenHein/react-native-shared-element) was a source of great inspiration for this project 🙏.\n\n#### Other Relevant Resources\n\n1. [material.io](https://material.io/design/motion/the-motion-system.html)\n2. [react-native-magic-move](https://github.com/IjzerenHein/react-native-magic-move)\n3. [Hein Rutjes React Europe Talk](https://www.youtube.com/watch?v=Uj7aWfrtey8\u0026list=FLsxiG7-SUK8s8xReSGAH4lQ)\n4. [Shared Element Transitions for Web](https://medium.com/@prateekbh/shared-elements-transitions-for-web-6fa9d31d4d6a)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsurdprofit%2Freact-motion-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabsurdprofit%2Freact-motion-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsurdprofit%2Freact-motion-router/lists"}