@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.
Files changed (2) hide show
  1. package/README.md +78 -168
  2. 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. Works in any framework or no framework at all.
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-git-main-vctqs1s-projects.vercel.app/
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
- Pick your framework below. For most SPA routers the Navigation API fires automatically after `registerNavProgressBar()` — no extra wiring needed. If you need to force a manual start signal, see [Manual start (non-Next.js)](#manual-start-non-nextjs) below.
19
+ ```ts
20
+ import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
65
21
 
66
- ### Next.js App Router
22
+ registerNavProgressBar();
23
+ getNavProgressBar()?.start();
24
+ ```
67
25
 
68
- The bar solves the `loading.js` dead gap — the frozen period between a user clicking a link and any loading feedback appearing. See [Next.js issue #43548](https://github.com/vercel/next.js/issues/43548).
26
+ ```html
27
+ <vctqs1-nav-progress-bar primary="#006bde"></vctqs1-nav-progress-bar>
28
+ ```
69
29
 
70
- This is the primary use case: start the bar on route departure, then let it finish automatically when the new App Router page commits.
30
+ If you want to start it manually from browser navigation events, feature-detect the Navigation API:
71
31
 
72
- **1. Add the React wrapper** (handles SSR rendering):
32
+ ```ts
33
+ const nav = (globalThis as { navigation?: EventTarget }).navigation;
73
34
 
74
- ```bash
75
- npm install @vctqs1/nav-progress-bar-react
35
+ if (nav?.addEventListener) {
36
+ nav.addEventListener('navigate', () => getNavProgressBar()?.start());
37
+ }
76
38
  ```
77
39
 
78
- **2. Add to your root layout** (`app/layout.tsx`):
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
- import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
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
- How the bar completes without a "done" callback — Next.js calls `history.pushState()` to update the URL, which fires the browser `navigatesuccess` event as a side effect. The web component listens for this internally and calls `finish()` automatically.
71
+ ## Features
111
72
 
112
- ```
113
- User clicks <Link>
114
- "navigate" fires instantly → bar starts (0ms)
115
- Next.js fetches RSC payload
116
- React patches the tree
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
- > 🎬 **Demo** — [watch the bar in action with Next.js App Router →](https://github.com/vctqs1/nav-progress-bar#nextjs-app-router)
79
+ ## API
122
80
 
123
- ---
81
+ ### `registerNavProgressBar(options?)`
124
82
 
125
- ### Nuxt
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
- // plugins/nav-progress-bar.client.ts
129
- import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
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
- ### SvelteKit
92
+ Returns the first `<vctqs1-nav-progress-bar>` element in the document, or `null`.
153
93
 
154
94
  ```ts
155
- // src/hooks.client.ts
156
- import { registerNavProgressBar } from '@vctqs1/nav-progress-bar';
157
- registerNavProgressBar();
95
+ getNavProgressBar()?.finish();
158
96
  ```
159
97
 
160
- ```svelte
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
- ### Astro
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
- ### Manual start (non-Next.js)
107
+ | Attribute | Type | Default | Description |
108
+ |---|---|---|---|
109
+ | `primary` | hex color or `--css-variable` | `#006bde` | Bar color. |
189
110
 
190
- Most SPA routers trigger browser navigation events automatically, so the bar starts/finishes on its own after `registerNavProgressBar()`.
191
- If you need to force an immediate start signal, add a guarded listener:
111
+ ## Color Configuration
192
112
 
193
- ```ts
194
- import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
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
- registerNavProgressBar();
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
- const nav = (globalThis as { navigation?: EventTarget }).navigation;
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
- ### Vanilla HTML (snippet)
126
+ ## How It Works
207
127
 
208
- ```html
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
- <vctqs1-nav-progress-bar></vctqs1-nav-progress-bar>
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
- ### ES Module
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
- ```ts
220
- import { registerNavProgressBar, getNavProgressBar } from '@vctqs1/nav-progress-bar';
136
+ ## Browser Support
221
137
 
222
- registerNavProgressBar();
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
- // The bar auto-starts on navigate and auto-finishes on navigatesuccess.
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
- ### Vanilla HTML (full page)
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
- ```html
235
- <!DOCTYPE html>
236
- <html>
237
- <body>
238
- <vctqs1-nav-progress-bar></vctqs1-nav-progress-bar>
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
- ## Color Configuration
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.1.2",
4
- "repository": "https://github.com/vctqs1/nav-progress-bar",
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",