From 2001e3e03204b434fa9e6f5772a89030c2c67b27 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 24 May 2022 00:23:46 +0800 Subject: [PATCH 01/10] feat: introduce `` --- .../src/app/components/nuxt-loading-bar.ts | 90 +++++++++++++++++++ packages/nuxt/src/core/nuxt.ts | 6 ++ 2 files changed, 96 insertions(+) create mode 100644 packages/nuxt/src/app/components/nuxt-loading-bar.ts diff --git a/packages/nuxt/src/app/components/nuxt-loading-bar.ts b/packages/nuxt/src/app/components/nuxt-loading-bar.ts new file mode 100644 index 00000000000..346f94dc654 --- /dev/null +++ b/packages/nuxt/src/app/components/nuxt-loading-bar.ts @@ -0,0 +1,90 @@ +import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue' +import { useNuxtApp } from '#app' + +export default defineComponent({ + name: 'NuxtLoadingBar', + props: { + throttle: { + type: Number, + default: 200 + }, + duration: { + type: Number, + default: 2000 + }, + height: { + type: Number, + default: 3 + }, + color: { + type: String, + default: 'repeating-linear-gradient(to right,#00dc82 0%,#34cdfe 50%,#0047e1 100%)' + } + }, + setup (props) { + const percent = ref(0) + const show = ref(false) + const step = computed(() => 10000 / props.duration) + + let _timer: any = null + let _throttle: any = null + + function clear () { + clearInterval(_timer) + clearTimeout(_throttle) + _timer = null + _throttle = null + } + function start () { + clear() + percent.value = 0 + if (props.throttle) { _throttle = setTimeout(startTimer, props.throttle) } else { startTimer() } + } + function increase (num: number) { + percent.value = Math.min(100, percent.value + num) + } + function finish () { + percent.value = 100 + hide() + } + function hide () { + clear() + setTimeout(() => { + show.value = false + setTimeout(() => { + percent.value = 0 + }, 400) + }, 500) + } + function startTimer () { + show.value = true + _timer = setInterval(() => { + increase(step.value) + }, 100) + } + + // Hooks + const nuxtApp = useNuxtApp() + nuxtApp.hook('page:start', start) + nuxtApp.hook('page:finish', finish) + onBeforeUnmount(() => clear) + + return () => h('div', { + class: 'nuxt-progress', + style: { + position: 'fixed', + top: 0, + right: 0, + left: 0, + pointerEvents: 'none', + width: `${percent.value}%`, + height: `${props.height}px`, + opacity: show.value ? 1 : 0, + background: props.color, + backgroundSize: `${(100 / percent.value) * 100}% auto`, + transition: 'width 0.1s, height 0.4s, opacity 0.4s', + zIndex: 999999 + } + }) + } +}) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 205336a74ca..db4b1143ce7 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -109,6 +109,12 @@ async function initNuxt (nuxt: Nuxt) { filePath: resolve(nuxt.options.appDir, 'components/nuxt-link') }) + // Add + addComponent({ + name: 'NuxtLoadingBar', + filePath: resolve(nuxt.options.appDir, 'components/nuxt-loading-bar') + }) + for (const m of modulesToInstall) { if (Array.isArray(m)) { await installModule(m[0], m[1]) From 8ad718579d5c2fc3c4b4b5a3624a10a4d00ae4b4 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 24 May 2022 15:51:20 +0800 Subject: [PATCH 02/10] docs: update --- .../3.api/2.components/4.nuxt-loading-bar.md | 35 +++++++++++++++++++ examples/routing/pages/app.vue | 1 + 2 files changed, 36 insertions(+) create mode 100644 docs/content/3.api/2.components/4.nuxt-loading-bar.md diff --git a/docs/content/3.api/2.components/4.nuxt-loading-bar.md b/docs/content/3.api/2.components/4.nuxt-loading-bar.md new file mode 100644 index 00000000000..14307c234c9 --- /dev/null +++ b/docs/content/3.api/2.components/4.nuxt-loading-bar.md @@ -0,0 +1,35 @@ +# `` + +::ReadMore{link="/guide/features/routing"} +:: + +Nuxt provides `` to display a progress bar on page navigation. + +## Examples + +### Basic usage + +Add `` in your `app.vue` or layouts. + +```vue [app.vue] + +``` + +:button-link[Open on StackBlitz]{href="https://stackblitz.com/github/nuxt/framework/tree/main/examples/routing/pages?terminal=dev&file=/app.vue" blank} + +## Props + +- **color**: The color for loading bar. +- **height**: Height of the loading bar, in pixels (deafult `3`). +- **duration**: Duration of the loading bar, in milliseconds (default `2000`). +- **throttle**: Throttle the appearing and hiding, in milliseconds (default `200`). + +::alert{type=info icon=🔎} +This component is completely optional. To have full customization, you can implement one your own based on [this file](https://github.com/nuxt/framework/blob/main/packages/nuxt/src/app/components/nuxt-loading-bar.ts). +:: + diff --git a/examples/routing/pages/app.vue b/examples/routing/pages/app.vue index 9f44a00aaa3..3ab0366b016 100644 --- a/examples/routing/pages/app.vue +++ b/examples/routing/pages/app.vue @@ -4,6 +4,7 @@ const route = useRoute()