/nextjs-morph-page-cabinet

A next.js page transition component that allows you to morph individual elements from one page to another, identified by their element id attribute.

Primary LanguageJavaScript

Next.js Page Transitions with Element Morphing

This is a fork of the original work done here https://github.com/illinois/next-page-transitions and adds new functionality to morph pages at an element-level.

Demo

You can see a basic demo of this library in action here: https://basic-usage-uwkrojwfad.now.sh/

The demo is hosted on now.js. Start-up times on the now.js containers can take a long time if they haven't been used for a while. Just click the link and be patient :)

Install

npm i nextjs-morph-page --save

Usage

Make sure that your app has a custom App component; if not, follow the example on the Next.js readme to create one. Then, in your App's render method, wrap the page Component in a MorphTransition component.

import App, { Container } from 'next/app'
import React from 'react'
import { MorphTransition } from 'next-page-transitions'

export default class MyApp extends App {
  static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  render() {
    const { Component, pageProps } = this.props;
    return (
      <Container>
        <MorphTransition timeout={300} classNames="page-transition">
          <Component {...pageProps} />
        </MorphTransition>
        <style jsx global>{`
          .page-transition-enter {
            opacity: 0;
          }
          .page-transition-enter-active {
            opacity: 1;
            transition: opacity 300ms;
          }
          .page-transition-exit {
            opacity: 1;
          }
          .page-transition-exit-active {
            opacity: 0;
            transition: opacity 300ms;
          }
        `}</style>
      </Container>
    )
  }
}

Whole-Page Based Transitions

When you move to a new page, the Component will change, and the MorphTransition component will detect that. Instead of immediately unmounting the page, it will apply the page-transition-exit class to a wrapper around the page to initialize the "exit" transition, and will then apply the page-transition-exit-active class as well to begin the transition. This is very similar to how the react-transition-group library does things things. After the previous page has been animated out, the new page is mounted and a similar pair of .page-transition-enter and page-transition-enter-active classes will be applied. This process repeats every time a new page is navigated to.

Element-Based Transitions

As you move from one page to another the individual elements on the page can also be "morphed" from the source / current page to the target / destination page. To indicate an element to be morphed you must provide the element with an id that is the SAME ON BOTH PAGES as well as a data-morph attribute indicating the number of milliseconds the element's morph should take.

The data-morph attribute only needs to exist on the source page. If you want transitions to occur on that element when the user navigates back from page 2 to page 1, as well as from page 1 to page 2, put a data-morph on the element on page 2 as well as page 1.

E.g:

Page 1

<img src="image1.jpg" id="test1" data-morph="300" />

Page 2

<img src="image2.jpg" id="test1" data-morph="300" />

Any css applied to the page 2 element "test1" will be applied as the morph transitions.

VERY IMPORTANT: The plugin does not currently support having style attributes on an element. If you apply styles directly on an element via the style="" attribute they will be wiped out when a morph is applied. Use css selectors only.