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:
parent
ee1b6d93ce
commit
f5402476cf
45
examples/with-next-page-transitions/README.md
Normal file
45
examples/with-next-page-transitions/README.md
Normal 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.
|
||||
|
30
examples/with-next-page-transitions/components/Loader.js
Normal file
30
examples/with-next-page-transitions/components/Loader.js
Normal 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
|
16
examples/with-next-page-transitions/package.json
Normal file
16
examples/with-next-page-transitions/package.json
Normal 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"
|
||||
}
|
67
examples/with-next-page-transitions/pages/_app.js
Normal file
67
examples/with-next-page-transitions/pages/_app.js
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
37
examples/with-next-page-transitions/pages/_document.js
Normal file
37
examples/with-next-page-transitions/pages/_document.js
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
51
examples/with-next-page-transitions/pages/about.js
Normal file
51
examples/with-next-page-transitions/pages/about.js
Normal 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
|
13
examples/with-next-page-transitions/pages/index.js
Normal file
13
examples/with-next-page-transitions/pages/index.js
Normal 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
|
Loading…
Reference in a new issue