Skip to content

Commit

Permalink
feat: add showSpinner prop
Browse files Browse the repository at this point in the history
  • Loading branch information
tomcru committed Jan 4, 2024
1 parent 12f507f commit a5dad41
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 6 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ export default function RootLayout({ children }) {
<HolyLoader
color="#ff4500"
height="1rem"
trickleSpeed={250}
speed={250}
easing="linear"
showSpinner
/>
{children}
</html>
Expand Down Expand Up @@ -106,5 +107,6 @@ onClick={(e) => {
- `speed` (number): Sets the animation speed of the top-loading bar in milliseconds. Default: 200 milliseconds.
- `zIndex` (number): Defines the z-index property of the top-loading bar, controlling its stacking order. Default: 2147483647.
- `boxShadow` (string): Sets the box-shadow property of the top-loading bar. Turned off by default.
- `showSpinner` (boolean): Determines whether to accompany the loading bar with a spinner. Turned off by default.

Project inspired by [nextjs-toploader](https://github.com/TheSGJ/nextjs-toploader) & [nprogress](https://github.com/rstacruz/nprogress)
72 changes: 67 additions & 5 deletions src/HolyProgress.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DEFAULTS } from './constants';

type HolyProgressProps = {
/**
* Specifies the minimum value for the progress bar to start at.
Expand Down Expand Up @@ -40,6 +42,12 @@ type HolyProgressProps = {
* For example: "0 0 10px #59a2ff, 0 0 5px #59a2ff"
*/
boxShadow?: string;

/**
* Specifies whether to accompany the loading bar with a spinner.
* Default: false
*/
showSpinner?: boolean;
};

type TransformStrategy = 'translate3d' | 'translate' | 'margin';
Expand Down Expand Up @@ -69,6 +77,7 @@ export class HolyProgress {
height: 4,
zIndex: 2147483647,
boxShadow: undefined,
showSpinner: false,
};

this.settings = { ...defaultSettings, ...customSettings };
Expand Down Expand Up @@ -119,9 +128,10 @@ export class HolyProgress {
progress.style.transition = 'all ' + speed + 'ms linear';
progress.style.opacity = '0';
setTimeout(() => {
this.remove();
this.removeBar();
next();
}, speed);
// this.removeSpinner();
}, speed);
} else {
setTimeout(next, speed);
Expand Down Expand Up @@ -179,6 +189,7 @@ export class HolyProgress {
}

this.startTrickle();
this.createSpinner();

return this;
};
Expand Down Expand Up @@ -318,6 +329,47 @@ export class HolyProgress {
return progress;
};

/**
* Creates and initializes a new spinner element in the DOM.
* It sets up the necessary styles and appends the element to the document body.
* @private
* @returns {void}
*/
private readonly createSpinner = (): void => {
const spinner = document.createElement('div');
spinner.id = 'holy-progress-spinner';
spinner.style.pointerEvents = 'none';

spinner.style.display = 'block';
spinner.style.position = 'fixed';
spinner.style.zIndex = this.settings.zIndex.toString();
spinner.style.top = '15px';
spinner.style.right = '15px';

spinner.style.width = '18px';
spinner.style.height = '18px';
spinner.style.boxSizing = 'border-box';

spinner.style.border = 'solid 2px transparent';
spinner.style.borderTopColor = DEFAULTS.color;
spinner.style.borderLeftColor = DEFAULTS.color;
spinner.style.borderRadius = '50%';
spinner.style.animation = 'holy-progress-spinner 400ms linear infinite';

const keyframes = `
@keyframes holy-progress-spinner {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;

const style = document.createElement('style');
style.innerHTML = keyframes;
spinner.appendChild(style);

document.body.appendChild(spinner);
};

/**
* Retrieves the existing progress bar element from the DOM, or creates a new one if not present.
* @private
Expand All @@ -337,12 +389,22 @@ export class HolyProgress {

/**
* Removes the progress bar element from the DOM.
* This is typically called when the progress reaches 100% and is no longer needed.
* @private
* @returns {void}
*/
private readonly removeBar = (): void => {
const bar = document.getElementById('holy-progress');
bar !== null && bar.remove();
};

/**
* Removes the spinner element from the DOM.
* @private
* @returns {void}
*/
private readonly remove = (): void => {
const progress = document.getElementById('holy-progress');
progress !== null && progress.remove();
private readonly removeSpinner = (): void => {
const spinner = document.getElementById('holy-progress-spinner');
spinner !== null && spinner.remove();
};

/**
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export const DEFAULTS = {
easing: 'ease',
speed: 200,
zIndex: 2147483647,
showSpinner: false,
};
8 changes: 8 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export interface HolyLoaderProps {
* For example: "0 0 10px #59a2ff, 0 0 5px #59a2ff"
*/
boxShadow?: string;

/**
* Specifies whether to accompany the loading bar with a spinner.
* Default: false
*/
showSpinner?: boolean;
}

/**
Expand Down Expand Up @@ -105,6 +111,7 @@ const HolyLoader = ({
speed = DEFAULTS.speed,
zIndex = DEFAULTS.zIndex,
boxShadow,
showSpinner = DEFAULTS.showSpinner,
}: HolyLoaderProps): null => {
React.useEffect(() => {
let holyProgress: HolyProgress;
Expand Down Expand Up @@ -174,6 +181,7 @@ const HolyLoader = ({
speed,
zIndex,
boxShadow,
showSpinner,
});

document.addEventListener('click', handleClick);
Expand Down

0 comments on commit a5dad41

Please sign in to comment.