EcoTracker-II / frontend /src /components /ui /LoadingSpinner.jsx
Akash-Dragon's picture
feat: build React/Vite frontend client with TailwindCSS
687ebbb
Raw
History Blame Contribute Delete
1.72 kB
import PropTypes from 'prop-types';
/**
* LoadingSpinner — accessible loading indicator with configurable size.
* Container includes aria-live="polite" and aria-busy="true" for assistive technologies.
* @param {Object} props
* @param {'sm'|'md'|'lg'|'xl'} [props.size='md'] - Spinner size variant
* @param {string} [props.className=''] - Additional CSS classes
* @param {string} [props.label='Loading...'] - Accessible label for screen readers
* @returns {JSX.Element}
*/
export default function LoadingSpinner({ size = 'md', className = '', label = 'Loading...' }) {
const sizes = {
sm: 'h-4 w-4 border-2',
md: 'h-8 w-8 border-2',
lg: 'h-12 w-12 border-3',
xl: 'h-16 w-16 border-4',
};
return (
<div
role="status"
aria-label={label}
aria-live="polite"
aria-busy="true"
className={`flex items-center justify-center ${className}`}
>
<div
className={`${sizes[size]} rounded-full animate-spin`}
style={{
borderColor: 'rgba(16, 185, 129, 0.2)',
borderTopColor: '#10b981',
}}
/>
<span className="sr-only">{label}</span>
</div>
);
}
LoadingSpinner.propTypes = {
size: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
className: PropTypes.string,
label: PropTypes.string,
};
/**
* PageLoader — full-page loading state with centered spinner and text.
* @returns {JSX.Element}
*/
export function PageLoader() {
return (
<div
className="min-h-[60vh] flex flex-col items-center justify-center gap-4"
aria-live="polite"
aria-busy="true"
>
<LoadingSpinner size="xl" />
<p className="text-slate-400 animate-pulse">Loading...</p>
</div>
);
}