1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Add example with next-page-transitions (#4404)

This commit is contained in:
Nathan Walters 2018-05-17 05:47:19 -05:00 committed by Tim Neutkens
parent ee1b6d93ce
commit f5402476cf
7 changed files with 259 additions and 0 deletions

View file

@ -0,0 +1,45 @@
[![Deploy to now](https://deploy.now.sh/static/button.svg)](https://deploy.now.sh/?repo=https://github.com/zeit/next.js/tree/master/examples/with-next-page-transitions)
# next-page-transitions example
## How to use
### Using `create-next-app`
Execute [`create-next-app`](https://github.com/segmentio/create-next-app) with [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) or [npx](https://github.com/zkat/npx#readme) to bootstrap the example:
```bash
npx create-next-app --example with-next-page-transitions with-next-page-transitions
# or
yarn create next-app --example with-next-page-transitions with-next-page-transitions
```
### Download manually
Download the example [or clone the repo](https://github.com/zeit/next.js):
```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-next-page-transitions
cd with-next-page-transitions
```
Install it and run:
```bash
npm install
npm run build
npm start
```
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download))
```bash
now
```
## The idea behind the example
The [`next-page-transitions`](https://github.com/illinois/next-page-transitions) library is a component that sits at the app level and allows you to animate page changes. It works especially nicely with apps with a shared layout element, like a navbar. This component will ensure that only one page is ever mounted at a time, and manages the timing of animations for you. This component works similarly to [`react-transition-group`](https://github.com/reactjs/react-transition-group) in that it applies classes to a container around your page; it's up to you to write the CSS transitions or animations to make things pretty!
This example includes two pages with links between them. The "About" page demonstrates how `next-page-transitions` makes it easy to add a loading state when navigating to a page: it will wait for the page to "load" its content (in this examples, that's simulated with a timeout) and then hide the loading indicator and animate in the page when it's done.

View file

@ -0,0 +1,30 @@
import React from 'react'
const Loader = () => (
<div className='loader'>
<style jsx>{`
.loader {
border: 8px solid #f3f3f3; /* Light grey */
border-top: 8px solid #3498db; /* Blue */
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 2s linear infinite;
margin-left: auto;
margin-right: auto;
margin-top: 40px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`}</style>
</div>
)
export default Loader

View file

@ -0,0 +1,16 @@
{
"name": "with-next-page-transitions",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"next-page-transitions": "1.0.0-alpha.2"
},
"license": "ISC"
}

View file

@ -0,0 +1,67 @@
import React from 'react'
import App, { Container } from 'next/app'
import { PageTransition } from 'next-page-transitions'
import Loader from '../components/Loader'
const TIMEOUT = 400
export default class MyApp extends App {
static async getInitialProps ({ Component, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
render () {
const { Component, pageProps } = this.props
return (
<Container>
<PageTransition
timeout={TIMEOUT}
classNames='page-transition'
loadingComponent={<Loader />}
loadingDelay={500}
loadingTimeout={{
enter: TIMEOUT,
exit: 0
}}
loadingClassNames='loading-indicator'
>
<Component {...pageProps} />
</PageTransition>
<style jsx global>{`
.page-transition-enter {
opacity: 0;
transform: translate3d(0, 20px, 0);
}
.page-transition-enter-active {
opacity: 1;
transform: translate3d(0, 0, 0);
transition: opacity ${TIMEOUT}ms, transform ${TIMEOUT}ms;
}
.page-transition-exit {
opacity: 1;
}
.page-transition-exit-active {
opacity: 0;
transition: opacity ${TIMEOUT}ms;
}
.loading-indicator-appear,
.loading-indicator-enter {
opacity: 0;
}
.loading-indicator-appear-active,
.loading-indicator-enter-active {
opacity: 1;
transition: opacity ${TIMEOUT}ms;
}
`}</style>
</Container>
)
}
}

View file

@ -0,0 +1,37 @@
import React from 'react'
import Document, { Head, Main, NextScript } from 'next/document'
export default class MyDocument extends Document {
static async getInitialProps (ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render () {
return (
<html lang='en'>
<Head>
<meta
name='viewport'
content='initial-scale=1.0, width=device-width'
/>
<link
rel='stylesheet'
href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css'
integrity='sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy'
crossOrigin='anonymous'
/>
<style>{`
.page {
height: 100vh;
}
`}</style>
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}

View file

@ -0,0 +1,51 @@
import React from 'react'
import PropTypes from 'prop-types'
import Link from 'next/link'
class About extends React.Component {
static pageTransitionDelayEnter = true
constructor (props) {
super(props)
this.state = {
loaded: false
}
}
componentDidMount () {
this.timeoutId = setTimeout(() => {
this.props.pageTransitionReadyToEnter()
this.setState({ loaded: true })
}, 2000)
}
componentWillUnmount () {
if (this.timeoutId) clearTimeout(this.timeoutId)
}
render () {
if (!this.state.loaded) return null
return (
<div className='container bg-success page'>
<h1>About us</h1>
<p>
Notice how a loading spinner showed up while my content was "loading"?
Pretty neat, huh?
</p>
<Link href='/'>
<a className='btn btn-light'>Go back home</a>
</Link>
</div>
)
}
}
About.propTypes = {
pageTransitionReadyToEnter: PropTypes.func
}
About.defaultProps = {
pageTransitionReadyToEnter: () => {}
}
export default About

View file

@ -0,0 +1,13 @@
import React from 'react'
import Link from 'next/link'
const Index = () => (
<div className='container bg-primary page'>
<h1>Hello, world!</h1>
<Link href='/about'>
<a className='btn btn-light'>About us</a>
</Link>
</div>
)
export default Index