Hone logo
Hone
Problems

React Progress Bar Component Challenge

Create a reusable and accessible progress bar component in React using TypeScript. This component is a fundamental UI element used to visualize the completion status of a task or process, providing immediate feedback to the user.

Problem Description

Your task is to build a ProgressBar React component that accepts a value prop representing the current progress (e.g., 50 for 50%) and an optional max prop (defaulting to 100) representing the maximum possible value. The component should visually display this progress.

Key Requirements:

  • Props:
    • value: A number representing the current progress. This should be a non-negative number.
    • max (optional): A number representing the maximum possible value. Defaults to 100. Must be a positive number.
  • Visual Representation:
    • The progress bar should have a container element and an inner element that fills up based on the value and max props.
    • The width of the inner element should be dynamically calculated as (value / max) * 100%.
  • Accessibility:
    • Implement ARIA attributes to ensure the progress bar is understandable by assistive technologies. Specifically, use role="progressbar", aria-valuenow, aria-valuemin, and aria-valuemax.
  • Styling:
    • The component should be stylable via CSS. You can assume basic styling will be provided or implement minimal inline styles for demonstration.
  • TypeScript:
    • All component props and internal logic should be typed using TypeScript.

Expected Behavior:

  • When value is 0, the progress bar should appear empty.
  • When value equals max, the progress bar should appear full.
  • When value is between 0 and max, the progress bar should be partially filled proportionally.
  • The component should gracefully handle edge cases like value exceeding max or value being negative.

Edge Cases:

  • value is negative.
  • value is greater than max.
  • max is 0 or negative.
  • value or max are not integers.

Examples

Example 1: Basic Usage

// Assume ProgressBar is imported and used like this:
<ProgressBar value={75} />

Output: A visual progress bar filled to 75% of its width. Explanation: max defaults to 100. The inner bar's width is calculated as (75 / 100) * 100% = 75%. ARIA attributes would be set as aria-valuenow={75}, aria-valuemin={0}, aria-valuemax={100}.

Example 2: Custom Max Value

// Assume ProgressBar is imported and used like this:
<ProgressBar value={30} max={50} />

Output: A visual progress bar filled to 60% of its width. Explanation: max is explicitly set to 50. The inner bar's width is calculated as (30 / 50) * 100% = 60%. ARIA attributes would be set as aria-valuenow={30}, aria-valuemin={0}, aria-valuemax={50}.

Example 3: Edge Case - Value Exceeding Max

// Assume ProgressBar is imported and used like this:
<ProgressBar value={120} max={100} />

Output: A visual progress bar filled to 100% of its width (capped at max). Explanation: Although value (120) is greater than max (100), the progress bar should visually represent 100% completion. The calculated width will be capped at 100%. ARIA attributes would reflect the actual value: aria-valuenow={120}, aria-valuemin={0}, aria-valuemax={100}.

Example 4: Edge Case - Negative Value

// Assume ProgressBar is imported and used like this:
<ProgressBar value={-10} max={100} />

Output: A visual progress bar that appears empty (0% filled). Explanation: A negative value should be treated as 0 for visual representation. The inner bar's width will be 0%. ARIA attributes would reflect the capped value: aria-valuenow={0}, aria-valuemin={0}, aria-valuemax={100}.

Constraints

  • The value prop must be a number. If a negative value is provided, it should be visually clamped to 0. If value exceeds max, it should be visually clamped to max.
  • The max prop, if provided, must be a positive number. If max is not a positive number (e.g., 0 or negative), the component should default to a sensible maximum (e.g., 100) or handle this gracefully. For this challenge, assume max will be a positive number if provided, or default to 100.
  • The component should render without errors and provide a functional progress bar for valid inputs.
  • Performance is not a primary concern for this specific challenge, but avoid unnecessary re-renders.

Notes

  • Consider how you will handle the dynamic width calculation. You can use inline styles or CSS classes.
  • Think about the semantic meaning of ARIA attributes and how they convey information to users of screen readers.
  • You might want to add a visual indicator for the percentage text, though this is not strictly required for the core functionality.
  • For accessibility, ensure the contrast ratio between the filled and unfilled parts of the bar is sufficient.
Loading editor...
typescript