UNPKG

react-busy-indicator

Version:

A stand-alone busy indicator for React.

89 lines (77 loc) 2.09 kB
import React, { useState } from 'react' const baseClass = 'BusyIndicator-'+Math.random().toString(36).slice(2) // Add busy indicator stylesheet var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = ` .${baseClass} { position: fixed; height: 3px; width: 100%; top: 0; left: 0; z-index: 1000; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; transform: scaleX(0); transform-origin: left center; transition: transform ease-in 300ms, opacity ease-in 300ms; transition-delay: 0; opacity: 0; } .${baseClass}.active { animation: ${baseClass} 2s cubic-bezier(.4,.45,.6,.55) infinite; animation-fill-mode: forwards; opacity: 1; } @keyframes ${baseClass} { 0% { transform: scaleX(0); } 10% { transform: scaleX(0.3); } 50% { transform: scaleX(0.7); } 90% { transform: scaleX(0.8); } 100% { transform: scaleX(1); } }`; document.getElementsByTagName('head')[0].appendChild(style); interface BusyIndicatorProps extends React.HTMLAttributes<any> { color?: string delayMs?: number isBusy?: boolean } export default function BusyIndicator({ className, color, active, isBusy, delayMs, style, ...props }) { let [hasRendered, setHasRendered] = useState(false) let isActive = active || isBusy // Prevent the `active` class from being applied on the first render, // to allow the CSS animation's delay prop to work even if `isActive` // is true when the component is mounted. if (!hasRendered) { isActive = false setTimeout(() => setHasRendered(true)) } // Only add the `active` class to this element while the // next page is loading, triggering a CSS animation to // show or hide the loading bar. return React.createElement('div', { ...props, className: `${baseClass} ${isActive ? 'active' : ''} ${className || ''}`, style: { backgroundColor: color, ...(isActive ? { transitionDelay: (delayMs || 0)+'ms', } : {}), ...style } }) } (BusyIndicator as any).defaultProps = { color: '#F54391', delayMs: 333, }