diff --git a/examples/with-loading/README.md b/examples/with-loading/README.md new file mode 100644 index 0000000000000..fcea460e5702d --- /dev/null +++ b/examples/with-loading/README.md @@ -0,0 +1,22 @@ +# Example app with page loading indicator + +This example features: + +* An app with two pages which uses a common [Header](./components/Header.js) component for navigation links. +* Customized version of [Link](./components/MyLink.js) which implements a loading indicator for client side navigations. +* Uses [nprogress](https://github.com/rstacruz/nprogress) as the loading indicator. + +## How to run it + +To run it: + +```sh +npm install +npm run dev +``` + +To deploy it, install [now](https://zeit.co/now) and run: + +```sh +now +``` diff --git a/examples/with-loading/components/Header.js b/examples/with-loading/components/Header.js new file mode 100644 index 0000000000000..20f037ec17a18 --- /dev/null +++ b/examples/with-loading/components/Header.js @@ -0,0 +1,19 @@ +import React from 'react' +import Head from 'next/head' +import MyLink from './MyLink' + +export default () => ( +
+ + {/* Import CSS for nprogress */} + + + + + Home + | + + About + +
+) diff --git a/examples/with-loading/components/MyLink.js b/examples/with-loading/components/MyLink.js new file mode 100644 index 0000000000000..78422f8542b8c --- /dev/null +++ b/examples/with-loading/components/MyLink.js @@ -0,0 +1,11 @@ +import React from 'react' +import Link from 'next/link' +import NProgress from 'nprogress' + +export default (props) => ( + NProgress.start()} + onComplete={() => NProgress.done()} + /> +) diff --git a/examples/with-loading/package.json b/examples/with-loading/package.json new file mode 100644 index 0000000000000..3146045703d3c --- /dev/null +++ b/examples/with-loading/package.json @@ -0,0 +1,14 @@ +{ + "name": "with-loading", + "version": "0.0.0", + "description": "", + "scripts": { + "dev": "next" + }, + "author": "", + "license": "ISC", + "dependencies": { + "nprogress": "^0.2.0", + "next": "*" + } +} diff --git a/examples/with-loading/pages/about.js b/examples/with-loading/pages/about.js new file mode 100644 index 0000000000000..5fd2ba798f779 --- /dev/null +++ b/examples/with-loading/pages/about.js @@ -0,0 +1,20 @@ +import React, { Component } from 'react' +import Header from '../components/Header' + +export default class About extends Component { + // Add some delay + static getInitialProps () { + return new Promise((resolve) => { + setTimeout(resolve, 500) + }) + } + + render () { + return ( +
+
+

This is about Next!

+
+ ) + } +} diff --git a/examples/with-loading/pages/index.js b/examples/with-loading/pages/index.js new file mode 100644 index 0000000000000..e147bfe8afa2e --- /dev/null +++ b/examples/with-loading/pages/index.js @@ -0,0 +1,9 @@ +import React from 'react' +import Header from '../components/Header' + +export default () => ( +
+
+

Hello Next!

+
+) diff --git a/examples/with-loading/static/nprogress.css b/examples/with-loading/static/nprogress.css new file mode 100644 index 0000000000000..12d8abdbf98c7 --- /dev/null +++ b/examples/with-loading/static/nprogress.css @@ -0,0 +1,73 @@ +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: #29d; + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px #29d, 0 0 5px #29d; + opacity: 1.0; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + display: block; + position: fixed; + z-index: 1031; + top: 15px; + right: 15px; +} + +#nprogress .spinner-icon { + width: 18px; + height: 18px; + box-sizing: border-box; + + border: solid 2px transparent; + border-top-color: #29d; + border-left-color: #29d; + border-radius: 50%; + + -webkit-animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + overflow: hidden; + position: relative; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + position: absolute; +} + +@-webkit-keyframes nprogress-spinner { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes nprogress-spinner { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/lib/link.js b/lib/link.js index cba86bb43bd76..96c8b2d763100 100644 --- a/lib/link.js +++ b/lib/link.js @@ -26,15 +26,22 @@ export default class Link extends Component { e.preventDefault() + // getting navigation event props. + const { + onStart = () => null, + onComplete = () => null, + onError = () => null + } = this.props + // straight up redirect + onStart() this.context.router.push(null, href) .then((success) => { + onComplete(success) if (!success) return if (scroll !== false) window.scrollTo(0, 0) }) - .catch((err) => { - if (this.props.onError) this.props.onError(err) - }) + .catch(onError) } render () {