@vctqs1/nav-progress-bar 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -168
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -1,83 +1,48 @@
|
|
|
1
1
|
# @vctqs1/nav-progress-bar
|
|
2
2
|
|
|
3
|
-
A zero-dependency, CSP-safe top-of-page progress bar built as a native Web Component.
|
|
3
|
+
A zero-dependency, CSP-safe top-of-page progress bar built as a native Web Component. It works in any framework or in plain HTML, and it is especially useful for Next.js App Router where `loading.tsx` does not appear until the RSC payload arrives.
|
|
4
4
|
|
|
5
|
-
> Live demo: https://nav-progress-bar
|
|
5
|
+
> Live demo: https://nav-progress-bar.vercel.app/
|
|
6
6
|
|
|
7
7
|
> Demo video:
|
|
8
8
|
|
|
9
9
|
<video src="https://github.com/user-attachments/assets/4144ed95-8c25-4aa9-b804-905ac24805b4" controls width="100%"></video>
|
|
10
10
|
|
|
11
|
-
> Originally built to solve the [Next.js App Router `loading.js` dead gap](https://github.com/vercel/next.js/issues/43548), but the underlying mechanism (the browser [Navigation API](https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API)) works anywhere.
|
|
12
|
-
|
|
13
|
-
> If you use Next.js App Router, this is the missing feedback layer before `loading.js` renders.
|
|
14
|
-
|
|
15
|
-
## Table of Contents
|
|
16
|
-
|
|
17
|
-
- [Features](#features)
|
|
18
|
-
- [Installation](#installation)
|
|
19
|
-
- [Packages](#packages)
|
|
20
|
-
- [Quick Start](#quick-start)
|
|
21
|
-
- [Next.js App Router](#nextjs-app-router)
|
|
22
|
-
- [Nuxt](#nuxt)
|
|
23
|
-
- [SvelteKit](#sveltekit)
|
|
24
|
-
- [Astro](#astro)
|
|
25
|
-
- [Manual start (non-Next.js)](#manual-start-non-nextjs)
|
|
26
|
-
- [Vanilla HTML](#vanilla-html-snippet)
|
|
27
|
-
- [ES Module](#es-module)
|
|
28
|
-
- [Color Configuration](#color-configuration)
|
|
29
|
-
- [API](#api)
|
|
30
|
-
- [How It Works](#how-it-works)
|
|
31
|
-
- [Browser Support](#browser-support)
|
|
32
|
-
- [Debugging](#debugging)
|
|
33
|
-
- [License](#license)
|
|
34
|
-
|
|
35
|
-
## Features
|
|
36
|
-
|
|
37
|
-
- **Zero dependencies** — pure Web Component, no React, no Vue, nothing
|
|
38
|
-
- **CSP-safe** — all styling via `adoptedStyleSheets`, no inline `style=` or `<style>` tags
|
|
39
|
-
- **SSR-ready** — supports Declarative Shadow DOM, no flash on hydration
|
|
40
|
-
- **Framework-agnostic** — Next.js, Nuxt, SvelteKit, Astro, Remix, vanilla HTML
|
|
41
|
-
- **Auto start/finish** — listens to browser Navigation API events automatically
|
|
42
|
-
- **Customisable color** — raw hex or CSS custom property
|
|
43
|
-
|
|
44
11
|
## Installation
|
|
45
12
|
|
|
46
13
|
```bash
|
|
47
|
-
npm install @vctqs1/nav-progress-bar
|
|
48
|
-
# or
|
|
49
14
|
pnpm add @vctqs1/nav-progress-bar
|
|
50
|
-
# or
|
|
51
|
-
yarn add @vctqs1/nav-progress-bar
|
|
52
15
|
```
|
|
53
16
|
|
|
54
|
-
## Packages
|
|
55
|
-
|
|
56
|
-
| Package | Description |
|
|
57
|
-
|---------|-------------|
|
|
58
|
-
| [`@vctqs1/nav-progress-bar`](https://www.npmjs.com/package/@vctqs1/nav-progress-bar) | Core Web Component — zero dependencies, framework-agnostic. Use this directly for vanilla HTML or non-React frameworks. |
|
|
59
|
-
| [`@vctqs1/nav-progress-bar-react`](https://www.npmjs.com/package/@vctqs1/nav-progress-bar-react) | React wrapper with SSR support and JSX types. Use this for React and especially Next.js App Router. |
|
|
60
|
-
|
|
61
|
-
|
|
62
17
|
## Quick Start
|
|
63
18
|
|
|
64
|
-
|
|
19
|
+
```ts
|
|
20
|
+
import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
65
21
|
|
|
66
|
-
|
|
22
|
+
registerNavProgressBar();
|
|
23
|
+
getNavProgressBar()?.start();
|
|
24
|
+
```
|
|
67
25
|
|
|
68
|
-
|
|
26
|
+
```html
|
|
27
|
+
<vctqs1-nav-progress-bar primary="#006bde"></vctqs1-nav-progress-bar>
|
|
28
|
+
```
|
|
69
29
|
|
|
70
|
-
|
|
30
|
+
If you want to start it manually from browser navigation events, feature-detect the Navigation API:
|
|
71
31
|
|
|
72
|
-
|
|
32
|
+
```ts
|
|
33
|
+
const nav = (globalThis as { navigation?: EventTarget }).navigation;
|
|
73
34
|
|
|
74
|
-
|
|
75
|
-
|
|
35
|
+
if (nav?.addEventListener) {
|
|
36
|
+
nav.addEventListener('navigate', () => getNavProgressBar()?.start());
|
|
37
|
+
}
|
|
76
38
|
```
|
|
77
39
|
|
|
78
|
-
|
|
40
|
+
### Next.js App Router
|
|
41
|
+
|
|
42
|
+
The bar fills the gap before `loading.tsx` becomes visible. The demo app in `apps/nextjs-app-router` uses a delayed product route to show the bar before the loading skeleton takes over.
|
|
79
43
|
|
|
80
44
|
```tsx
|
|
45
|
+
// app/layout.tsx
|
|
81
46
|
import NavProgressBar from '@vctqs1/nav-progress-bar-react';
|
|
82
47
|
|
|
83
48
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
@@ -92,160 +57,105 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
92
57
|
}
|
|
93
58
|
```
|
|
94
59
|
|
|
95
|
-
**3. Create `instrumentation-client.ts`** at the project root:
|
|
96
|
-
|
|
97
60
|
```ts
|
|
98
|
-
|
|
61
|
+
// instrumentation-client.ts
|
|
62
|
+
import { getNavProgressBar, registerNavProgressBar } from '@vctqs1/nav-progress-bar-react';
|
|
99
63
|
|
|
100
64
|
registerNavProgressBar();
|
|
101
65
|
|
|
102
|
-
export function onRouterTransitionStart(
|
|
103
|
-
url: string,
|
|
104
|
-
navigationType: 'push' | 'replace' | 'traverse',
|
|
105
|
-
) {
|
|
66
|
+
export function onRouterTransitionStart() {
|
|
106
67
|
getNavProgressBar()?.start();
|
|
107
68
|
}
|
|
108
69
|
```
|
|
109
70
|
|
|
110
|
-
|
|
71
|
+
## Features
|
|
111
72
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
→ history.pushState() finalises
|
|
118
|
-
→ "navigatesuccess" fires → bar finishes
|
|
119
|
-
```
|
|
73
|
+
- Zero dependencies
|
|
74
|
+
- CSP-safe styling via `adoptedStyleSheets`
|
|
75
|
+
- Declarative Shadow DOM support for SSR
|
|
76
|
+
- Navigation API lifecycle handling for `navigate` and `navigatesuccess`
|
|
77
|
+
- Optional `primary` color override via attribute or registration options
|
|
120
78
|
|
|
121
|
-
|
|
79
|
+
## API
|
|
122
80
|
|
|
123
|
-
|
|
81
|
+
### `registerNavProgressBar(options?)`
|
|
124
82
|
|
|
125
|
-
|
|
83
|
+
Registers the `<vctqs1-nav-progress-bar>` custom element. Calling it more than once is safe. Registration is skipped if the browser does not support the Navigation API.
|
|
126
84
|
|
|
127
85
|
```ts
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
export default defineNuxtPlugin(() => {
|
|
132
|
-
registerNavProgressBar();
|
|
133
|
-
|
|
134
|
-
const router = useRouter();
|
|
135
|
-
router.beforeEach(() => getNavProgressBar()?.start());
|
|
136
|
-
// finish() is handled automatically by navigatesuccess
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
```html
|
|
141
|
-
<!-- app.vue -->
|
|
142
|
-
<template>
|
|
143
|
-
<div>
|
|
144
|
-
<vctqs1-nav-progress-bar></vctqs1-nav-progress-bar>
|
|
145
|
-
<NuxtPage />
|
|
146
|
-
</div>
|
|
147
|
-
</template>
|
|
86
|
+
registerNavProgressBar();
|
|
87
|
+
registerNavProgressBar({ primary: '#fff' });
|
|
148
88
|
```
|
|
149
89
|
|
|
150
|
-
|
|
90
|
+
### `getNavProgressBar()`
|
|
151
91
|
|
|
152
|
-
|
|
92
|
+
Returns the first `<vctqs1-nav-progress-bar>` element in the document, or `null`.
|
|
153
93
|
|
|
154
94
|
```ts
|
|
155
|
-
|
|
156
|
-
import { registerNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
157
|
-
registerNavProgressBar();
|
|
95
|
+
getNavProgressBar()?.finish();
|
|
158
96
|
```
|
|
159
97
|
|
|
160
|
-
|
|
161
|
-
<!-- src/routes/+layout.svelte -->
|
|
162
|
-
<vctqs1-nav-progress-bar></vctqs1-nav-progress-bar>
|
|
163
|
-
<slot />
|
|
164
|
-
```
|
|
98
|
+
### Instance methods
|
|
165
99
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
```astro
|
|
171
|
-
---
|
|
172
|
-
// src/layouts/BaseLayout.astro
|
|
173
|
-
---
|
|
174
|
-
<html>
|
|
175
|
-
<body>
|
|
176
|
-
<vctqs1-nav-progress-bar></vctqs1-nav-progress-bar>
|
|
177
|
-
<slot />
|
|
178
|
-
<script>
|
|
179
|
-
import { registerNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
180
|
-
registerNavProgressBar();
|
|
181
|
-
</script>
|
|
182
|
-
</body>
|
|
183
|
-
</html>
|
|
184
|
-
```
|
|
100
|
+
| Method | Description |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `start()` | Begins the indeterminate progress animation and returns `this`. |
|
|
103
|
+
| `finish()` | Completes the bar to 100% and fades it out, then returns `this`. |
|
|
185
104
|
|
|
186
|
-
|
|
105
|
+
### Attribute
|
|
187
106
|
|
|
188
|
-
|
|
107
|
+
| Attribute | Type | Default | Description |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| `primary` | hex color or `--css-variable` | `#006bde` | Bar color. |
|
|
189
110
|
|
|
190
|
-
|
|
191
|
-
If you need to force an immediate start signal, add a guarded listener:
|
|
111
|
+
## Color Configuration
|
|
192
112
|
|
|
193
|
-
```
|
|
194
|
-
|
|
113
|
+
```html
|
|
114
|
+
<vctqs1-nav-progress-bar primary="#006bde"></vctqs1-nav-progress-bar>
|
|
115
|
+
<vctqs1-nav-progress-bar primary="--your-brand-color"></vctqs1-nav-progress-bar>
|
|
116
|
+
```
|
|
195
117
|
|
|
196
|
-
|
|
118
|
+
The component resolves `primary="--token"` to `var(--token, #006bde)` inside its shadow root, so it can inherit document-level CSS custom properties.
|
|
197
119
|
|
|
198
|
-
|
|
199
|
-
if (nav?.addEventListener) {
|
|
200
|
-
nav.addEventListener('navigate', () => getNavProgressBar()?.start());
|
|
201
|
-
}
|
|
202
|
-
```
|
|
120
|
+
Priority order:
|
|
203
121
|
|
|
204
|
-
|
|
122
|
+
1. HTML attribute `primary="..."`
|
|
123
|
+
2. `registerNavProgressBar({ primary: '...' })`
|
|
124
|
+
3. Hardcoded fallback `#006bde`
|
|
205
125
|
|
|
206
|
-
|
|
126
|
+
## How It Works
|
|
207
127
|
|
|
208
|
-
|
|
209
|
-
<script type="module">
|
|
210
|
-
import { registerNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
211
|
-
registerNavProgressBar();
|
|
212
|
-
</script>
|
|
128
|
+
The component uses Shadow DOM and two constructable stylesheets:
|
|
213
129
|
|
|
214
|
-
|
|
215
|
-
|
|
130
|
+
- A layout sheet for the fixed top-of-page positioning
|
|
131
|
+
- A color sheet for the active/completed states
|
|
132
|
+
- A progress sheet that rewrites only the width rule during animation
|
|
216
133
|
|
|
217
|
-
|
|
134
|
+
Progress eases toward 85% every 200ms and finishes at 100% before fading out. The timing is intentionally indeterminate so the bar feels responsive without pretending to know exact load progress.
|
|
218
135
|
|
|
219
|
-
|
|
220
|
-
import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
136
|
+
## Browser Support
|
|
221
137
|
|
|
222
|
-
|
|
138
|
+
Requires the [Navigation API](https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API). Chrome and Edge support it; unsupported browsers skip registration gracefully.
|
|
223
139
|
|
|
224
|
-
|
|
225
|
-
// You can also control it manually:
|
|
226
|
-
getNavProgressBar()?.start();
|
|
227
|
-
getNavProgressBar()?.finish();
|
|
228
|
-
```
|
|
140
|
+
## Framework Notes
|
|
229
141
|
|
|
230
|
-
|
|
142
|
+
The core package is framework-agnostic. Common patterns:
|
|
231
143
|
|
|
232
|
-
|
|
144
|
+
- Next.js App Router: render the element in `app/layout.tsx` and start it from `instrumentation-client.ts`
|
|
145
|
+
- React SPA: register once and call `start()` from your router transition hooks if needed
|
|
146
|
+
- Vanilla HTML: add the custom element to the page and call `registerNavProgressBar()` in a module script
|
|
233
147
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
<script type="module">
|
|
241
|
-
import { registerNavProgressBar } from '@vctqs1/nav-progress-bar';
|
|
242
|
-
registerNavProgressBar();
|
|
243
|
-
</script>
|
|
244
|
-
</body>
|
|
245
|
-
</html>
|
|
148
|
+
## Development
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
pnpm install
|
|
152
|
+
pnpm nx build nav-progress-bar
|
|
153
|
+
pnpm nx test nav-progress-bar
|
|
246
154
|
```
|
|
247
155
|
|
|
248
|
-
##
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
|
249
159
|
|
|
250
160
|
Two formats are supported for the `primary` attribute:
|
|
251
161
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vctqs1/nav-progress-bar",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"repository":
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/vctqs1/nav-progress-bar.git",
|
|
7
|
+
"directory": "packages/nav-progress-bar"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://nav-progress-bar.vercel.app",
|
|
5
10
|
"type": "module",
|
|
6
11
|
"main": "./dist/index.js",
|
|
7
12
|
"module": "./dist/index.js",
|
|
@@ -21,6 +26,12 @@
|
|
|
21
26
|
"license": "MIT",
|
|
22
27
|
"keywords": [
|
|
23
28
|
"toploader",
|
|
29
|
+
"nextjs-toploader",
|
|
30
|
+
"nextjs toploader",
|
|
31
|
+
"nextjs top loader",
|
|
32
|
+
"nextjs progress bar",
|
|
33
|
+
"app router progress bar",
|
|
34
|
+
"route transition loader",
|
|
24
35
|
"progress-bar",
|
|
25
36
|
"navigation",
|
|
26
37
|
"web-component",
|