Hone logo
Hone
Problems

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:

  1. Component Structure: Create a React functional component named LoadingSpinner that accepts props for customization.
  2. Visual Representation: The spinner should be implemented using CSS. You can choose any common CSS animation technique (e.g., rotation, pulsing).
  3. TypeScript Integration: The component and its props must be defined using TypeScript.
  4. 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. If false, the spinner should not be rendered.
  5. 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.)
  6. Accessibility: Consider basic accessibility for the spinner.

Expected Behavior:

  • When isLoading is true, the LoadingSpinner component should render and display the animated spinner with the specified size, color, and thickness.
  • When isLoading is false, the LoadingSpinner component should render null or 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 size and thickness props 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 size prop should be a positive integer representing pixels.
  • The color prop should be a valid CSS color string (e.g., "red", "#FF0000", "rgba(255, 0, 0, 0.5)").
  • The thickness prop should be a positive integer representing pixels.
  • The isLoading prop 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 transform and animation properties.
Loading editor...
typescript