Extract hand-rolled progress meter into shared ui/ProgressBar - #4243
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Six surfaces had each re-implemented the same
h-1.5 rounded-fulltrack +style={{ width:${pct}%}}fill, and they had already drifted on accessibility — only two carriedrole="progressbar"witharia-valuenow, so the rest were invisible to a screen reader.client/src/components/ui/ProgressBar.jsx. It always emits the ARIA trio (role="progressbar",aria-valuenow,aria-valuemin,aria-valuemax) plus an accessible name fromlabel, which defaults toProgressso a bar is never nameless.percent(clamped 0..100),tone(accent / accent2 / success / warning / error / muted),label,size(smh-1.5,mdh-2),track(bgon a card,borderon the page ground),duration(static Tailwind class map — an interpolatedduration-${n}is invisible to the build), andclassNamefor layout only.percentfollows the repo's sentinel rule:null/undefinedmeans unmeasurable and draws the indeterminate pulse with noaria-valuenow(the LoRA installer gets noContent-Lengthfrom some mirrors), while a non-finite number is a broken measurement (a0 / 0ratio) and renders an empty determinate bar rather than silently claiming indeterminate.Migrated call sites — no behavior change beyond the added ARIA:
client/src/pages/Loras.jsxclient/src/components/pipeline/manuscript/ManuscriptReadAloud.jsxclient/src/components/pipeline/stages/EpisodeVideoStage.jsxclient/src/components/meatspace/post/PostLlmDrillRunner.jsxclient/src/components/meatspace/post/MemoryPractice.jsxclient/src/components/pipeline/AutopilotMilestones.jsxThe two files that had a local component literally named
ProgressBarkeep a thin domain wrapper over the shared primitive —PromptProgress(the "Prompt N of M" counter) andPracticeProgress— so the shared meter is the only thing drawing a bar. Consolidating the drill runner's training block intoPromptProgressremoved 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 isrounded-fulllike the other five instead ofrounded.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
client/src/components/ui/ProgressBar.test.jsx(29 cases): ARIA trio + accessible name, the default name when a host omitslabel, fill width, clamping above 100 / below 0, roundedaria-valuenowwith a fractional width preserved,NaN/Infinityreading as an empty determinate bar rather than the indeterminate pulse,null/undefinedproducing the pulse with noaria-valuenowbut with the bounds intact, every tone class, unknown-tone fallback, size/track switching,classNamepass-through, and the static duration map with its fallback.cd client && npm test— 640/641 files pass. The one failure issrc/pages/MoodBoardDetail.test.jsx(aGalleryImagePickeract-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-warningsclean on all eight touched files.src/a11yConventions.test.jspasses.