Back

Progress Bar I

easy

Streak

0 days

Progress

0%

Submitted

0

Progress Bar I

React30 mineasyFreeNew

Prompt

Progress Bar I is the foundational version: a controlled bar that accepts a value (0–100) prop and renders a filled track with a percentage label. It looks simple but tests CSS width animation, ARIA accessibility, and prop validation — all essentials in component-library interviews.

Build a ProgressBar component with a smooth width transition, a visible percentage label, and full accessibility: role="progressbar", aria-valuenow, aria-valuemin, aria-valuemax. Support a color prop for theming.

The demo should include a live slider that drives the progress bar value so interviewers can see it animate in real time.

Requirements

  • →Accepts value (0-100), color, and label props
  • →Smooth CSS width transition on value change
  • →role=progressbar with aria-valuenow/min/max
  • →Clamp value between 0 and 100
  • →Show percentage text inside or above the bar
  • →Configurable color via prop
Example
Loading preview...
For the best coding experience, we recommend using a desktop device.
Preparing Sandbox...
Premium interview report

What interviewers score in this build

Use this before reading the code. It tells you what to say, what to test, and where machine-coding candidates usually lose points.

Interview signals

  • CSS width transition: transition: width on fill div, no JS animation
  • ARIA attributes: role=progressbar, aria-valuenow/min/max on fill element
  • Value clamping: Math.min/max guards against out-of-range props
  • Prop-driven theming: color prop applied as background style

Time checkpoints

  1. 1

    0–3 min: Explain CSS width transition approach

  2. 2

    3–8 min: Build track and fill with width: value%

  3. 3

    8–12 min: Add transition and clamp logic

  4. 4

    12–16 min: Add ARIA attributes for accessibility

Edge-case checklist

Empty data and first-load state
Slow network, failed request, and retry path
Keyboard navigation and focus movement
Large input size, re-render pressure, and cleanup

Common mistakes

  • Starting with JSX before naming state and events.
  • Ignoring accessibility until the final minute.
  • Over-building abstractions instead of finishing the required behavior.
  • Failing to narrate trade-offs while coding.
SolutionRead-only · Live Preview

Technical Explanation

Why This Question Exists

Progress Bar I is a component-library design question. It looks trivial — a div with a width — but the interviewer is checking for CSS animation correctness, defensive prop handling, full ARIA accessibility, and whether you know when to use CSS transitions vs JS animation. Most candidates pass the visual test but fail the ARIA audit.

CSS Width Transition — not JS

/* ✅ CORRECT — GPU-accelerated, smooth, zero JS */
.fill {
  width: var(--progress, 0%);  /* or inline style */
  transition: width 0.35s ease;
}

/* ❌ WRONG — JS animation loop, janky, burns CPU */
useEffect(() => {
  let frame;
  const animate = () => {
    setDisplayWidth(w => w + 1);
    if (displayWidth < target) frame = requestAnimationFrame(animate);
  };
  frame = requestAnimationFrame(animate);
  return () => cancelAnimationFrame(frame);
}, [target]);

CSS transitions run on the compositor thread — they don't block JavaScript and produce silky-smooth 60fps animation even under load. JS-driven animation competes with React's reconciler for the main thread.

ℹ Interview Tip

Say: "I use CSS transition on the width property rather than a JavaScript animation loop. CSS transitions run on the GPU compositor thread independently of JavaScript, so the bar animates smoothly even if the main thread is busy processing a large React update."

Full ARIA Implementation

<div
  role="progressbar"
  aria-valuenow={value}
  aria-valuemin={0}
  aria-valuemax={100}
  aria-label="Upload progress"  // OR aria-labelledby pointing to a label element
  style={{ width: value + '%' }}
/>

Screen readers announce this as "Upload progress, 45 percent" automatically from these four attributes. Without them, the progress bar is completely invisible to users who rely on assistive technology — a WCAG 2.1 Level A failure.

Value Clamping — defensive component design

function ProgressBar({ value = 0 }) {
  // Guard at the component boundary — protect against invalid props
  const clamped = Math.min(100, Math.max(0, Number(value) || 0));
  // Now clamped is always 0-100, even if caller passes:
  // value={-10}  → 0
  // value={150}  → 100
  // value="50"   → 50 (Number() coerces string)
  // value={NaN}  → 0  (|| 0 handles NaN)
  // value={null} → 0
  return <div style={{ width: clamped + '%' }} />;
}

Color and Label Props

function ProgressBar({ value, color = '#6366f1', label = 'Progress', showLabel = true }) {
  const v = Math.min(100, Math.max(0, value));
  return (
    <div>
      {showLabel && (
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <span>{label}</span>
          <span>{v}%</span>
        </div>
      )}
      <div className="track">
        <div role="progressbar" aria-valuenow={v} aria-valuemin={0} aria-valuemax={100}
          style={{ width: v + '%', background: color, transition: 'width .35s' }} />
      </div>
    </div>
  );
}
⚠ Common Pitfall: Animating transform instead of width

Some developers use transform: scaleX(value/100) thinking it's more performant. While transform is GPU-accelerated, scaleX scales from the centre by default — the fill shrinks/grows symmetrically. Use transform-origin: left to fix this, OR just use width — the performance difference is negligible for a simple progress bar.

Interview Criteria

CSS width transition

transition: width on fill div, no JS animation

ARIA attributes

role=progressbar, aria-valuenow/min/max on fill element

Value clamping

Math.min/max guards against out-of-range props

Prop-driven theming

color prop applied as background style

Accessible label

Visible label and percentage shown

Time Checkpoints

0–3 min

0–3 min: Explain CSS width transition approach

3–8 min

3–8 min: Build track and fill with width: value%

8–12 min

8–12 min: Add transition and clamp logic

12–16 min

12–16 min: Add ARIA attributes for accessibility

16–20 min

16–20 min: Add color and label props

20–25 min

20–25 min: Build demo with live slider

Streak

0 days

Last active: Sign in to track

Progress

0%

0/0 solved

Submitted

0

Solutions pushed to review history.