Skip to content

Commit a5dad41

Browse files
committed
feat: add showSpinner prop
1 parent 12f507f commit a5dad41

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ export default function RootLayout({ children }) {
7575
<HolyLoader
7676
color="#ff4500"
7777
height="1rem"
78-
trickleSpeed={250}
78+
speed={250}
7979
easing="linear"
80+
showSpinner
8081
/>
8182
{children}
8283
</html>
@@ -106,5 +107,6 @@ onClick={(e) => {
106107
- `speed` (number): Sets the animation speed of the top-loading bar in milliseconds. Default: 200 milliseconds.
107108
- `zIndex` (number): Defines the z-index property of the top-loading bar, controlling its stacking order. Default: 2147483647.
108109
- `boxShadow` (string): Sets the box-shadow property of the top-loading bar. Turned off by default.
110+
- `showSpinner` (boolean): Determines whether to accompany the loading bar with a spinner. Turned off by default.
109111

110112
Project inspired by [nextjs-toploader](https://github.com/TheSGJ/nextjs-toploader) & [nprogress](https://github.com/rstacruz/nprogress)

src/HolyProgress.ts

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { DEFAULTS } from './constants';
2+
13
type HolyProgressProps = {
24
/**
35
* Specifies the minimum value for the progress bar to start at.
@@ -40,6 +42,12 @@ type HolyProgressProps = {
4042
* For example: "0 0 10px #59a2ff, 0 0 5px #59a2ff"
4143
*/
4244
boxShadow?: string;
45+
46+
/**
47+
* Specifies whether to accompany the loading bar with a spinner.
48+
* Default: false
49+
*/
50+
showSpinner?: boolean;
4351
};
4452

4553
type TransformStrategy = 'translate3d' | 'translate' | 'margin';
@@ -69,6 +77,7 @@ export class HolyProgress {
6977
height: 4,
7078
zIndex: 2147483647,
7179
boxShadow: undefined,
80+
showSpinner: false,
7281
};
7382

7483
this.settings = { ...defaultSettings, ...customSettings };
@@ -119,9 +128,10 @@ export class HolyProgress {
119128
progress.style.transition = 'all ' + speed + 'ms linear';
120129
progress.style.opacity = '0';
121130
setTimeout(() => {
122-
this.remove();
131+
this.removeBar();
123132
next();
124133
}, speed);
134+
// this.removeSpinner();
125135
}, speed);
126136
} else {
127137
setTimeout(next, speed);
@@ -179,6 +189,7 @@ export class HolyProgress {
179189
}
180190

181191
this.startTrickle();
192+
this.createSpinner();
182193

183194
return this;
184195
};
@@ -318,6 +329,47 @@ export class HolyProgress {
318329
return progress;
319330
};
320331

332+
/**
333+
* Creates and initializes a new spinner element in the DOM.
334+
* It sets up the necessary styles and appends the element to the document body.
335+
* @private
336+
* @returns {void}
337+
*/
338+
private readonly createSpinner = (): void => {
339+
const spinner = document.createElement('div');
340+
spinner.id = 'holy-progress-spinner';
341+
spinner.style.pointerEvents = 'none';
342+
343+
spinner.style.display = 'block';
344+
spinner.style.position = 'fixed';
345+
spinner.style.zIndex = this.settings.zIndex.toString();
346+
spinner.style.top = '15px';
347+
spinner.style.right = '15px';
348+
349+
spinner.style.width = '18px';
350+
spinner.style.height = '18px';
351+
spinner.style.boxSizing = 'border-box';
352+
353+
spinner.style.border = 'solid 2px transparent';
354+
spinner.style.borderTopColor = DEFAULTS.color;
355+
spinner.style.borderLeftColor = DEFAULTS.color;
356+
spinner.style.borderRadius = '50%';
357+
spinner.style.animation = 'holy-progress-spinner 400ms linear infinite';
358+
359+
const keyframes = `
360+
@keyframes holy-progress-spinner {
361+
0% { transform: rotate(0deg); }
362+
100% { transform: rotate(360deg); }
363+
}
364+
`;
365+
366+
const style = document.createElement('style');
367+
style.innerHTML = keyframes;
368+
spinner.appendChild(style);
369+
370+
document.body.appendChild(spinner);
371+
};
372+
321373
/**
322374
* Retrieves the existing progress bar element from the DOM, or creates a new one if not present.
323375
* @private
@@ -337,12 +389,22 @@ export class HolyProgress {
337389

338390
/**
339391
* Removes the progress bar element from the DOM.
340-
* This is typically called when the progress reaches 100% and is no longer needed.
341392
* @private
393+
* @returns {void}
394+
*/
395+
private readonly removeBar = (): void => {
396+
const bar = document.getElementById('holy-progress');
397+
bar !== null && bar.remove();
398+
};
399+
400+
/**
401+
* Removes the spinner element from the DOM.
402+
* @private
403+
* @returns {void}
342404
*/
343-
private readonly remove = (): void => {
344-
const progress = document.getElementById('holy-progress');
345-
progress !== null && progress.remove();
405+
private readonly removeSpinner = (): void => {
406+
const spinner = document.getElementById('holy-progress-spinner');
407+
spinner !== null && spinner.remove();
346408
};
347409

348410
/**

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export const DEFAULTS = {
55
easing: 'ease',
66
speed: 200,
77
zIndex: 2147483647,
8+
showSpinner: false,
89
};

src/index.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ export interface HolyLoaderProps {
4646
* For example: "0 0 10px #59a2ff, 0 0 5px #59a2ff"
4747
*/
4848
boxShadow?: string;
49+
50+
/**
51+
* Specifies whether to accompany the loading bar with a spinner.
52+
* Default: false
53+
*/
54+
showSpinner?: boolean;
4955
}
5056

5157
/**
@@ -105,6 +111,7 @@ const HolyLoader = ({
105111
speed = DEFAULTS.speed,
106112
zIndex = DEFAULTS.zIndex,
107113
boxShadow,
114+
showSpinner = DEFAULTS.showSpinner,
108115
}: HolyLoaderProps): null => {
109116
React.useEffect(() => {
110117
let holyProgress: HolyProgress;
@@ -174,6 +181,7 @@ const HolyLoader = ({
174181
speed,
175182
zIndex,
176183
boxShadow,
184+
showSpinner,
177185
});
178186

179187
document.addEventListener('click', handleClick);

0 commit comments

Comments
 (0)