Skip to content

fix(Progress): clear stale segment values when flipping to indeterminate - #843

Open
sridhar-3009 wants to merge 3 commits into
vuetifyjs:devfrom
sridhar-3009:fix/progress-indeterminate-stale-state-814
Open

fix(Progress): clear stale segment values when flipping to indeterminate#843
sridhar-3009 wants to merge 3 commits into
vuetifyjs:devfrom
sridhar-3009:fix/progress-indeterminate-stale-state-814

Conversation

@sridhar-3009

Copy link
Copy Markdown
Contributor

Fixes #814

Root cause

EmProgress.vue passes :model-value="indeterminate ? undefined : model" to Progress.Root. When indeterminate flips to true after a value was already committed, ProgressRoot's internal computed collapses to [], and useProxyModel calls context.apply([]).

createProgress.apply() only wrote incoming values to segments at matching array indices:

for (const [index, element] of clamped.entries()) {
  const ticket = segments.value[index]
  if (!ticket || !isRef(ticket.value) || isReadonly(ticket.value)) continue
  ticket.value.value = element!
}

clamped.entries() is empty when incoming is [], so the loop body never runs — any already-registered segment keeps its old value. isIndeterminate derives from segment values (> 0 means determinate), so it stayed false, and ProgressRoot kept emitting data-state="determinate" and the stale aria-valuenow/aria-valuetext even while Emerald's CSS sweep animation was visibly running — a real accessibility bug (AT reports a fixed value while the bar visually reads as busy/indeterminate).

Fix

apply() now iterates over every registered segment instead of only the incoming array, so a segment with no corresponding entry resets to min:

for (const [index, ticket] of segments.value.entries()) {
  if (!isRef(ticket.value) || isReadonly(ticket.value)) continue
  ticket.value.value = clamped[index] ?? min
}

Since apply() is always called with the full desired model state (see useProxyModel's reconcile), this is the correct general semantic — not specific to the indeterminate case — and doesn't affect any of the existing apply tests (single segment, multi-segment, clamping, pending-registration).

Also fixed the smaller item the issue flagged: the stale comment in EmProgress.vue claiming ProgressRoot always emits aria-labelledby — it's gated on hasLabel (ProgressRoot.vue:144).

Test plan

  • Reproduced against the pre-fix code first: added a v-model test that commits a value, then transitions to undefined via wrapper.setProps — failed on main (total stayed 60 instead of resetting to 0), passes with the fix
  • pnpm vitest run --project v0:unit → 4700 passed, 1 skipped (no change from baseline)
  • pnpm --filter=@vuetify/v0 typecheck and pnpm --filter=@paper/emerald typecheck clean
  • pnpm eslint clean on changed files
  • Added a changeset (patch bump for @vuetify/v0 and @paper/emerald)

apply() only wrote incoming values to segments at matching array
indices, so apply([]) - what happens when a bound model value becomes
undefined - left previously-registered segments at their old value.
Flipping EmProgress's indeterminate prop after a value was already
committed ran the CSS sweep animation correctly but data-state stayed
"determinate" and aria-valuenow/aria-valuetext kept reporting the
stale committed value to assistive tech.

apply() now walks every registered segment instead of just the
incoming array, resetting any segment without a corresponding entry
back to min.

Also fixes a stale comment in EmProgress.vue claiming ProgressRoot
always emits aria-labelledby; it's gated on hasLabel.
…set branches

Adds two apply() cases the codecov patch check flagged as uncovered:
skipping a readonly segment, and resetting a segment with no
corresponding incoming entry back to min.
@johnleider johnleider added this to the v1.0.x milestone Aug 20, 2026
…ances

The initial value option pinned isIndeterminate to false permanently, even after segments registered and were cleared back to min. Scope the pin to the zero-segment state, mirroring total's fallback, so registered segments are the sole source of truth once they exist.
@johnleider johnleider added the T: bug Something isn't working label Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants