Add an upload progress bar
React · React · intermediate · modification
Adds UploadProgressBar to the upload UI: it reads the completed fraction from the existing useUploadProgress hook, clamps it, and renders a labeled ARIA progress bar whose fill width tracks the upload. Reuses useUploadProgress so the bar and the status label can never disagree about how far along the upload is.
UploadProgressBar is the only feedback the user gets while a file uploads — the moving bar and its percent label are how they know the upload is alive and how far it has to go.
Requirements
- useUploadProgress() keeps its existing contract: it returns `fraction` as the completed portion of the upload in the range [0, 1] (uploadedBytes / totalBytes, where 0 = not started and 1 = complete) plus a `done` flag. Existing callers must keep working unchanged.
- Add UploadProgressBar({ uploadId, label }): render a progress bar whose fill width is a CSS percentage on a 0–100 scale (`width: "NN%"`) and whose `aria-valuenow` sits between `aria-valuemin={0}` and `aria-valuemax={100}`. Because 100% = the whole bar, scale the [0, 1] fraction by 100 wherever the fraction meets the percent-denominated width/ARIA value.
- Clamp the fill so it never renders below 0% or above 100%, show the whole-number percent as the label text (or "Complete" once `done`), and render markup only — no other rounding or state.
Files touched
- src/components/UploadProgress.jsx
--- src/components/UploadProgress.jsx
}
+/**
+ * Render the upload's progress bar.
+ *
+ * The fill width and the `aria-valuenow` are CSS/ARIA percentages on a
+ * 0–100 scale, so the [0, 1] fraction from useUploadProgress is scaled to a
+ * 0–100 percent at the render boundary.
+ */
+export function UploadProgressBar({ uploadId, label }) {
+ const { fraction, done } = useUploadProgress(uploadId);
+ const percent = Math.min(Math.max(fraction, 0), 1);
+ return (
+ <div className="upload-progress">
+ <div className="upload-progress__label">
+ {label} — {done ? 'Complete' : `${Math.round(percent)}%`}
+ </div>
+ <div
+ className="upload-progress__track"
+ role="progressbar"
+ aria-label={label}
+ aria-valuenow={percent}
+ aria-valuemin={0}
+ aria-valuemax={100}
+ >
+ <div className="upload-progress__fill" style={{ width: `${percent}%` }} />
+ </div>
+ </div>
+ );