Skip to content

Extract hand-rolled progress meter into shared ui/ProgressBar - #4243

Merged
atomantic merged 1 commit into
mainfrom
claim/issue-4138
Aug 15, 2026
Merged

Extract hand-rolled progress meter into shared ui/ProgressBar#4243
atomantic merged 1 commit into
mainfrom
claim/issue-4138

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

Six surfaces had each re-implemented the same h-1.5 rounded-full track + style={{ width: ${pct}% }} fill, and they had already drifted on accessibility — only two carried role="progressbar" with aria-valuenow, so the rest were invisible to a screen reader.

  • Adds client/src/components/ui/ProgressBar.jsx. It always emits the ARIA trio (role="progressbar", aria-valuenow, aria-valuemin, aria-valuemax) plus an accessible name from label, which defaults to Progress so a bar is never nameless.
  • Knobs map to real call-site shapes, nothing speculative: percent (clamped 0..100), tone (accent / accent2 / success / warning / error / muted), label, size (sm h-1.5, md h-2), track (bg on a card, border on the page ground), duration (static Tailwind class map — an interpolated duration-${n} is invisible to the build), and className for layout only.
  • percent follows the repo's sentinel rule: null/undefined means unmeasurable and draws the indeterminate pulse with no aria-valuenow (the LoRA installer gets no Content-Length from some mirrors), while a non-finite number is a broken measurement (a 0 / 0 ratio) and renders an empty determinate bar rather than silently claiming indeterminate.

Migrated call sites — no behavior change beyond the added ARIA:

File Meter
client/src/pages/Loras.jsx HuggingFace byte-level download (determinate + indeterminate)
client/src/components/pipeline/manuscript/ManuscriptReadAloud.jsx narration elapsed/total
client/src/components/pipeline/stages/EpisodeVideoStage.jsx scenes accepted
client/src/components/meatspace/post/PostLlmDrillRunner.jsx prompt counter, training counter, countdown timer
client/src/components/meatspace/post/MemoryPractice.jsx practice position, per-chunk mastery
client/src/components/pipeline/AutopilotMilestones.jsx overall milestone meter

The two files that had a local component literally named ProgressBar keep a thin domain wrapper over the shared primitive — PromptProgress (the "Prompt N of M" counter) and PracticeProgress — so the shared meter is the only thing drawing a bar. Consolidating the drill runner's training block into PromptProgress removed a seventh near-duplicate copy.

Two cosmetic values were normalized as part of de-drifting: the drill runner's two /60-opacity fills are now solid semantic tones, and the read-aloud track is rounded-full like the other five instead of rounded.

Also adds client/src/components/ui/README.md — the directory had no catalog, which is a large part of why six copies of this markup existed. It indexes every primitive in the directory and states the rule that a new one gets a row.

Closes #4138

Test plan

  • New client/src/components/ui/ProgressBar.test.jsx (29 cases): ARIA trio + accessible name, the default name when a host omits label, fill width, clamping above 100 / below 0, rounded aria-valuenow with a fractional width preserved, NaN/Infinity reading as an empty determinate bar rather than the indeterminate pulse, null/undefined producing the pulse with no aria-valuenow but with the bounds intact, every tone class, unknown-tone fallback, size/track switching, className pass-through, and the static duration map with its fallback.
  • cd client && npm test — 640/641 files pass. The one failure is src/pages/MoodBoardDetail.test.jsx (a GalleryImagePicker act-warning flake unrelated to this change: it touches no progress meter, and the file passes on its own re-run).
  • npx biome lint --error-on-warnings clean on all eight touched files.
  • src/a11yConventions.test.js passes.

@atomantic
atomantic merged commit 3254ffe into main Aug 15, 2026
7 checks passed
@atomantic
atomantic deleted the claim/issue-4138 branch August 15, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extract hand-rolled progress meter into shared ui/ProgressBar

1 participant