Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Simple Demo

react-transpose

NPM

react-transpose is a set of tools which helps you animate route or component transitions. It also enables you to animate shared-element transitions.

This package makes use of the awesome library popmotion for it's animations. This means that under the hood it uses the same spring / tween / etc.. animations types, and since this is a react package, it has some strong simularities with react-pose. In a way, this package can be seen as an extension on top of react-pose.

Why not use PoseGroup?

While PoseGroup is excellent in most use-cases probably way more suffisticated, sometimes it's hard to handle route specific configuration. What if you wanted to animate the entering direction of a component based on the route it was comming from? That's where react-transpose comes in: for each transition-state (enter / exit) it gives you additional props for acting on specific route-transitions. On top of that this package provides tools to create so called shared-element transitions.

Install

npm install --save react-transpose

or

yarn add react-transpose

This package has a peer-dependency on popmotion, so make sure to install this package together with popmotion@^8.6.0. If your project is using popmotion's react-pose there is no need to install popmotion since react-pose already has a dependency on it.

Usage

Simple demo

Simple Demo

Edit react-transpose simple demo

import * as React from "react";
import { SwitchGroup, Stage, transposedShared } from "react-transpose";

const Box = transposedShared.div({
  // declare which style-props should be animated
  animationProps: ["width", "height", "backgroundColor"],
  // standard react-pose transition config
  transition: {
    // animation type (spring / tween / keyframes / etc...)
    type: "tween",
    duration: 300
  },
  // for identifying shared elements
  sharedKey: "box"
});

function App() {
  const [currentStage, setStage] = React.useState("route-a");

  // toggle stage every second
  React.useEffect(() => {
    const id = setInterval(() => {
      setStage(currentStage =>
        currentStage === "route-a" ? "route-b" : "route-a"
      );
    }, 1000);

    return () => clearInterval(id);
  }, []);

  return (
    <div style={{ position: "relative" }}>
      <SwitchGroup stage={currentStage}>
        <Stage
          stage="route-a"
          render={() => (
            <div style={{ position: "absolute" }}>
              <Box
                style={{ width: 100, height: 100, backgroundColor: "blue" }}
              />
            </div>
          )}
        />
        <Stage
          stage="route-b"
          render={() => (
            <div style={{ position: "absolute" }}>
              <Box
                style={{ width: 200, height: 200, backgroundColor: "red" }}
              />
            </div>
          )}
        />
      </SwitchGroup>
    </div>
  );
}

Other demo's

API

SwitchGroup

It's main purpose is to render the right <Stage /> out of one or multiple stages (paths/routes) given a current stage. It has a similar function to Switch in react-router.

Prop type required Description
children ReactNode[] yes Must be one or more <Stage /> elements
stage string yes the current stage
setStage (stage: string) => void no Use in combination with useStage to set a stage from deeper within the tree

example

import { SwitchGroup, Stage } from "react-transpose";

function App() {
  const [currentStage, setStage] = React.useState("a");

  return (
    <SwitchGroup stage={currentStage} setStage={setStage}>
      <Stage stage="a" render={() => <div>A</div>} />
      <Stage stage="b" render={() => <div>B</div>} />
    </SwitchGroup>
  );
}

Stage

Used to represent a stage or path, much like a <Route /> in react-router. Use either the render or the component prop.

Prop type required Description
stage string yes
render () => ReactElement no
component Component no

useStage

Helper hook to set a stage from deeper within the tree. Note: the 'setStage' prop must be given to the <SwitchGroup /> component.

import { useStage } from "react-transpose";

function Route() {
  const { setStage } = useStage();

  return <button onClick={() => setStage("next")}>Goto next route</button>;
}

Group

Similar to <SwitchGroup />, but lets you handle the routing mechanism. Useful in combination with react-router for example.

Prop type required Description
currentPath string yes path of current location
children ReactElement yes Can only be one child at a time

example with react-router

function App({ location }) {
  return (
    <Group currentPath={location.pathname}>
      <Switch location={location}>
        <Route exact path={"/"} component={Home} />
        <Route exact path={"/about"} component={About} />
      </Switch>
    </Group>
  );
}

transposed

Function which creates components with animation capabilities. As with libraries as styled-components and react-pose, you can either pass in a existing component (don't forgot to forward the ref to a dom-node), or a tag name. So these all work:

// existing component
import Box from "./Box";
const AnimatedBox = transposed(Box)({});

// argument string
const AnimatedBox = transposed("div")({});

// helper method
const AnimatedBox = transposed.div({});

Config

Prop type required Description
animateFirst boolean no defaults to false. Determines whether to animate entering the first route
enter `object (props: TransitionProps) => object` yes
exit `object (props: TransitionProps) => object` yes

The enter and exit prop takes either a function returning an object, or a plain object. It is almost the same as how react-pose does it. For example:

const Box = transposed.div({
  enter: {
    // style props...
    opacity: 1,
    x: 0,
    backgroundColor: 'red',
    transition: { // info about transition
      type: "spring"
      stiffness: 200, // specfic spring prop
      damping: 25,  // specfic spring prop
      delay: 500 // different from react-pose
    }
  },
  exit: {
    opacity: 0,
    x: 100,
    backgroundColor: 'blue',
    transition: {
      type: "tween"
      duration: 400 // specific tween prop
    }
  }
})

When passing a function, you'll get a object with these properties

Prop Type Description
path { from: string: to: string }
props object Provides access to the wrapped component's props
direction `"in" "out"`

For example:

const Box = transposed.div({
  enter: ({ props }) => ({
    opacity: 1,
    x: 0,
    transition: {
      type: "spring",
      delay: props.index * 100 // staggering effect
    }
  }),
  exit: ({ path, direction }) => ({
    opacity: 0,
    // animate differently based on direction and path.from
    x: path.from === "a" && direction === "in" ? -100 : 300
  })
});

transposedShared

Quite similar to transposed, but it's main purpose is to animate shared-element transitions.

Config

Prop type required Description
sharedKey `string (props: object) => string` yes
animationProps string[] yes style-props to be animated
transition `object (props: TransitionProps) => object` yes
whenNotShared { enter: object; exit: object; animatedFirst: boolean } no see below

Example:

Edit react-transposed transposedShared-example

const Box = transposedShared.div({
  sharedKey: props => props.id,
  animationProps: ["x", "y", "width", "height"],
  transition: {
    type: "spring",
    stiffness: 400,
    damping: 30
  },
  // (optional) practically same as transposed config
  whenNotShared: {
    enter: { opacity: 1 },
    exit: { opacity: 0 }
  }
});

const BoxContext = React.createContext();

function List() {
  const { gotoDetail } = React.useContext(BoxContext);

  return (
    <div>
      <Box id="1" onClick={() => gotoDetail("1")} />
      <Box id="2" onClick={() => gotoDetail("2")} />
      <Box id="3" onClick={() => gotoDetail("3")} />
      <Box id="4" onClick={() => gotoDetail("4")} />
    </div>
  );
}

function Detail() {
  const { gotoList, selectedBox } = React.useContext(BoxContext);

  return (
    <>
      <button onClick={gotoList}>Back</button>
      <Box id={selectedBox} />
    </>
  );
}

function App() {
  const [state, setState] = React.useState({
    stage: "list",
    selectedBox: null
  });

  const payload = React.useMemo(
    () => ({
      ...state,
      gotoDetail: box => setState({ stage: "detail", selectedBox: box }),
      gotoList: box => setState({ stage: "list", selectedBox: null })
    }),
    [state]
  );

  return (
    <BoxContext.Provider value={payload}>
      <SwitchGroup stage={state.stage}>
        <Stage stage="list" component={List} />
        <Stage stage="detail" component={Detail} />
      </SwitchGroup>
    </BoxContext.Provider>
  );
}

License

MIT © everweij

About

Set of tools which helps you animate route / component transitions

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published