{"id":15387577,"url":"https://github.com/nicolasdelfino/react-metro","last_synced_at":"2025-08-21T16:08:48.925Z","repository":{"id":57334543,"uuid":"103060023","full_name":"nicolasdelfino/react-metro","owner":"nicolasdelfino","description":"A lightweight engine to animate dom elements as they mount or unmount","archived":false,"fork":false,"pushed_at":"2018-07-25T18:13:44.000Z","size":462,"stargazers_count":281,"open_issues_count":0,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-31T14:13:13.848Z","etag":null,"topics":["animation","react","react-metro"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nicolasdelfino.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-10T20:36:54.000Z","updated_at":"2025-02-24T12:57:04.000Z","dependencies_parsed_at":"2022-09-06T05:21:58.967Z","dependency_job_id":null,"html_url":"https://github.com/nicolasdelfino/react-metro","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdelfino%2Freact-metro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdelfino%2Freact-metro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdelfino%2Freact-metro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nicolasdelfino%2Freact-metro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nicolasdelfino","download_url":"https://codeload.github.com/nicolasdelfino/react-metro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675596,"owners_count":20977376,"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","react","react-metro"],"created_at":"2024-10-01T14:54:10.482Z","updated_at":"2025-04-07T15:06:05.012Z","avatar_url":"https://github.com/nicolasdelfino.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"http://nicolasdelfino.com/metro_web_text.png\" alt=\"metro logo\" /\u003e\n\u003c/p\u003e\n\n[![Build Status](https://travis-ci.org/nicolasdelfino/react-metro.svg?branch=master)](https://travis-ci.org/nicolasdelfino/react-metro) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/nicolasdelfino/react-metro/issues)\n\n\u003e A tiny configurable wrapper for animating dom elements as they mount or unmount\n\n* Optional hooks for binding to mount / unmount sequence complete.\n* Comes with a simple fade animation but everything can be overriden by providing a custom animationsMap\n* 3.3KB minimized / gzipped\n\n#### Codesandbox demo\n\n\u003ca href=\"https://codesandbox.io/s/w0orz7j5p8\" target=\"_blank\"\u003e\n\u003cimg src=\"https://camo.githubusercontent.com/416c7a7433e9d81b4e430b561d92f22ac4f15988/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667\" alt=\"edit metro on codesandbox\" /\u003e\u003c/a\u003e\n\n#### Medium\n\n\u003ca href=\"https://medium.com/@nicolasdelfino/introducing-react-metro-f766068212d5\" target=\"_blank\"\u003eIntroducing React Metro\u003c/a\u003e\n\n### Important note:\n\n1.9.1 uses custom tweener MetroTween.js, list of supported easing equations in docs.\n\n#### Usage\n\nInstall\n\n```javascript\nnpm install react-metro\n```\n\nImport\n\n```javascript\nimport Metro from \"react-metro\";\n```\n\n#### Metro.sequence - animate multiple objects:\n\nCreate a sequence, map it:\n\n```javascript\n// in method renderMetroComponents:\n\n// mount / unmount\nif (!this.state.showMetroComponents) {\n  return null;\n}\n\nconst data = [\"cat\", \"dog\"];\n\nreturn Metro.sequence(\n  data,\n  animationsMap, // optional\n  defaultAnimation // optional\n).map(data =\u003e {\n  return (\n    \u003cMetro.animation\n      {...data}\n      wrapperType=\"div\" // optional ul or whatever, defaults to div\n      onClick={this.onClick.bind(this)} // optional\n      enableClickDuringAnimation //optional, boolean (default false)\n      onMount={this.onMountComplete.bind(this)} // optional\n      onUnmount={this.onUnmountComplete.bind(this)} // optional\n    \u003e\n      {\" \"}\n      // optional\n      \u003cYourComponent {...data.content} /\u003e\n    \u003c/Metro.animation\u003e\n  );\n});\n```\n\n\u0026 render it:\n\n```javascript\n\u003cTransitionGroupPlus\u003e\n  {\" \"}\n  // optional arg type=\"li/div/ul...\"\n  {this.renderMetroComponents()}\n\u003c/TransitionGroupPlus\u003e\n```\n\n#### Metro.container - single node enhancer:\n\n```javascript\nrenderMetroContainer() {\n  if (!this.state.showContainer) {\n    return null;\n  }\n\n  const props = {\n    wrapperType: \"div\",\n    enableClickDuringAnimation: true,\n    onMount: this.wrapMount.bind(this),\n    onUnmount: this.wrapUnmount.bind(this)\n  };\n\n  return Metro.container(\n    \u003cdiv\u003e...\u003c/div\u003e, // base node: pass in text, wrap components\n    containerAnimation, // optional\n    props //optional\n  );\n}\n```\n\n#### Metro.bindContainer:\n\n```javascript\n// A wrapper for Metro.container that removes the need for having a conditional toggle in parent.\n// Arguments:\n// conditional property for toggling (bool), component (dom element), animation (object - optional), props (object optional)\n\nrenderLessVerboseContainer() {\n  return Metro.bindContainer(bool, component, animation, props)\n}\n```\n\n#### Customizing animations\n\n```javascript\n// Override Metro´s default animations settings for each unique item in your items\n// array, see MetroTween args further down.\n// The animation settings are combined with the default animation settings, so\n// you only have to specify the values you want to change.\nconst animationMap = [\n  {\n    in: {\n      time: 3,\n      delay: 0\n    },\n    out: {\n      time: 1.4,\n      delay: 1\n    },\n    willEnter: {\n      from: { opacity: 0, y: 120, x: 30 },\n      to: { opacity: 1, y: 0, x: 0, ease: \"easeInOutExpo\" }\n    }\n  },\n  {\n    out: {\n      time: 1.4,\n      delay: 0\n    },\n    willEnter: {\n      from: { opacity: 0, y: 120, x: -30 },\n      to: { opacity: 1, y: 0, x: 0, ease: \"easeInOutExpo\" }\n    }\n  }\n];\n\n// Metro comes with a simple, fade in / out default. This object passed\n// in as the third argument in the Metro.sequence overrides the default settings.\n// The override settings are combined with the built in defaults, so you only\n// have to specify the values you want to change.\nconst defaultAnimationOverride = {\n  animation: {\n    out: {\n      time: 0.5,\n      delay: 0\n    },\n    in: {\n      time: 1,\n      delay: 0\n    },\n    willEnter: {\n      from: { opacity: 0, y: 50 },\n      to: { opacity: 1, y: 0, ease: \"easeInOutQuad\" }\n    },\n    willLeave: {\n      from: {\n        opacity: 1,\n        y: 0\n      },\n      to: { opacity: 0, y: 50, ease: \"easeInOutQuad\" }\n    }\n  }\n};\n```\n\n#### MetroTween\n\nMetroTween is Metro's new tween engine that replaces GSAP TweenMax.\nIt's 100% backward compatible with everything used in the codesandbox demo.\n\n#### Supported tween equations:\n\n```javascript\neaseInSine;\neaseOutSine;\neaseInOutSine;\neaseInQuad;\neaseOutQuad;\neaseInOutQuad;\neaseInCubic;\neaseOutCubic;\neaseInOutCubic;\neaseInQuart;\neaseOutQuart;\neaseInOutQuart;\neaseInQuint;\neaseOutQuint;\neaseInOutQuint;\neaseInExpo;\neaseOutExpo;\neaseInOutExpo;\neaseInCirc;\neaseOutCirc;\neaseInOutCirc;\neaseInBack;\neaseOutBack;\neaseInOutBack;\n```\n\n#### Tweenable properties\n\n```javascript\nx;\ny;\nskewX;\nskewY;\nscaleX;\nscaleY;\nrotation;\nscale;\n```\n\n#### Methods\n\n```javascript\nwrapperType; // dom element, defaults to div\nonClick; // receives props (original array data), array index and animating\nenableClickDuringAnimation; // boolean, defaults to false\nonMount; // fires when the mount sequence completes\nonUnmount; // fires when the unmount sequence completes\n```\n\n#### Advanced usage\n\nThe real power of Metro shines through it's use of dynamic animationMaps.\n\n\u003ca href=\"https://codesandbox.io/s/w0orz7j5p8\" target=\"_blank\"\u003eThe second demo\u003c/a\u003e demonstrates the concept of dynamic sequences. This is achieved by altering the sequence´s animationMap on user interaction.\n\nWe define an animatonMap to achieve the delayed entrance effect we want. Since the active animationMap is stored in our wrapper component´s local state we can replace our initial map on user interaction, thus making the animation interactive.\n\nEven though the developer has total control of an animation through the use of custom animationMaps, we created a helper method called Metro.generateFocusMap for cases where you want to accentuate a specific item within your sequence without having to write logic.\n\nThese presets - today a total of 4: verticalDelayed, dominoForwards, dominoBackwards, dominoMulti, is something that you as a developer are more than welcome to contribute to. Ideas for upcoming presets are stuff like 'checkerBoard' / 'wave' / 'circular' etc...\n\nEach preset should try to incorporate the focus-first logic as they are intended to accentuate a clicked component.\nCurrent api for using the method is:\n\n```javascript\nconst domino = Metro.generateFocusMap(\n  index, //focus - index of clicked component\n  6, // columns\n  this.state.data.length, // length of sequence\n  this.state.preset // preset - dynamic in state or put directly as string 'dominoMulti'\n  duration // optional (default 1 second)\n)\nthis.setState({animationMap: domino}) // -\u003e do unmount logic...\n```\n\n#### Contribute\n\n##### PRs\n\nPRs are welcomed, to contribute make sure that:\n\n* Branch name references issue number if it adresses a feature / bug fix.\n* Branch has already been [synced with the upstream repo](https://help.github.com/articles/syncing-a-fork/) and any merge-conflicts have been resolved.\n* Install eslint and prettier to avoid lint issues while developing\n* Use \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003esemantic release guidelines\u003c/a\u003e when commiting\n\n##### Contributors\n\n\u003cimg src=\"https://avatars3.githubusercontent.com/u/26581738?v=4\u0026s=400\" width=\"70px;\"/\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/emilpalsson\"\u003e\u003csub\u003eEmil Pålsson\u003c/sub\u003e\u003c/a\u003e\n\n##### Issues\n\nPlease be descriptive\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasdelfino%2Freact-metro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnicolasdelfino%2Freact-metro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnicolasdelfino%2Freact-metro/lists"}