React Loading Spinner Component
This challenge focuses on building a reusable and customizable loading spinner component in React using TypeScript. Loading spinners are essential UI elements for indicating that an operation is in progress, improving user experience by providing visual feedback and preventing user interaction with non-responsive elements.
Problem Description
Your task is to create a functional React component named LoadingSpinner that displays a visual indicator of ongoing activity. This component should be easily integrated into any React application and offer a degree of customization for its appearance.
Key Requirements:
- Component Structure: Create a React functional component named
LoadingSpinnerthat accepts props for customization. - Visual Representation: The spinner should be implemented using CSS. You can choose any common CSS animation technique (e.g., rotation, pulsing).
- TypeScript Integration: The component and its props must be defined using TypeScript.
- Customization Props: The component should accept at least the following props:
size: A number representing the desired diameter of the spinner in pixels.color: A string representing the CSS color value for the spinner.thickness: A number representing the border-width (thickness) of the spinner in pixels.isLoading: A boolean prop that controls whether the spinner is visible or not. Iffalse, the spinner should not be rendered.
- Styling: The spinner's styling should be applied internally using CSS Modules or styled-components, ensuring encapsulation. (For this challenge, CSS Modules is recommended for simplicity.)
- Accessibility: Consider basic accessibility for the spinner.
Expected Behavior:
- When
isLoadingistrue, theLoadingSpinnercomponent should render and display the animated spinner with the specifiedsize,color, andthickness. - When
isLoadingisfalse, theLoadingSpinnercomponent should rendernullor nothing. - The spinner should animate continuously.
Edge Cases:
- Invalid Prop Types: While TypeScript helps prevent this at compile time, consider how the component might behave if default values were not explicitly set or if unexpected values were somehow passed.
- Zero or Negative Dimensions: The
sizeandthicknessprops should ideally handle non-positive values gracefully (e.g., default to a sensible value or render nothing).
Examples
Example 1: Basic Spinner
// App.tsx
import React, { useState } from 'react';
import LoadingSpinner from './LoadingSpinner'; // Assuming LoadingSpinner.tsx is in the same directory
function App() {
const [loading, setLoading] = useState(true);
return (
<div>
<h1>My App</h1>
<button onClick={() => setLoading(!loading)}>Toggle Loading</button>
{loading && (
<LoadingSpinner
size={50}
color="#3498db"
thickness={5}
isLoading={loading}
/>
)}
<p>Content below the spinner...</p>
</div>
);
}
export default App;
Output (when loading is true):
A blue circular spinner with a diameter of 50px and a thickness of 5px will be displayed.
Explanation:
The App component conditionally renders the LoadingSpinner based on the loading state. When loading is true, the spinner is displayed with the provided size, color, and thickness.
Example 2: Smaller, Thicker Spinner
// Another component or part of App.tsx
<LoadingSpinner
size={30}
color="green"
thickness={8}
isLoading={true}
/>
Output:
A green circular spinner with a diameter of 30px and a thickness of 8px will be displayed.
Explanation:
Demonstrates changing the appearance of the spinner by modifying the size, color, and thickness props.
Example 3: Spinner Not Visible
// Part of App.tsx
<LoadingSpinner
size={50}
color="#f39c12"
thickness={3}
isLoading={false} // Spinner will not render
/>
Output:
Nothing will be rendered by the LoadingSpinner component.
Explanation:
When isLoading is false, the component correctly renders nothing, allowing other content to be displayed.
Constraints
- The
sizeprop should be a positive integer representing pixels. - The
colorprop should be a valid CSS color string (e.g., "red", "#FF0000", "rgba(255, 0, 0, 0.5)"). - The
thicknessprop should be a positive integer representing pixels. - The
isLoadingprop must be a boolean. - The spinner animation should be smooth and performant.
- The component should be pure (no side effects beyond rendering).
Notes
- Consider using CSS Modules for styling to ensure that styles are scoped to your component and do not leak to other parts of your application.
- For accessibility, you might consider adding an
aria-live="polite"attribute to the spinner's container if it's dynamically shown/hidden to inform screen readers. - Think about default values for props to make the component easier to use in common scenarios.
- The exact animation technique is up to you, but a common approach is to use CSS
transformandanimationproperties.