Skip to content

fix(match-list): scope drag ids to response areas so re-used answer choices behave independently PIE-965 - #3115

Merged
CarlaCostea merged 1 commit into
developfrom
fix/PIE-965
Sep 4, 2026
Merged

fix(match-list): scope drag ids to response areas so re-used answer choices behave independently PIE-965#3115
CarlaCostea merged 1 commit into
developfrom
fix/PIE-965

Conversation

@CarlaCostea

Copy link
Copy Markdown
Contributor

The issue was caused by duplicate placed answers sharing the same dnd-kit id. Since dnd-kit uses that id for its draggable registry, state, and transform, multiple tiles collapsed into a single entry. This caused them to animate together, sometimes update the wrong response area, and in some cases become focusable but no longer draggable.

Placed answers now use their response area as the draggable id, while pool choices keep using the choice id since each appears only once.

I also fixed a missing placeAnswer case: with duplicates enabled, moving a placed answer onto an occupied response area was previously a no-op. It now replaces the target and clears the source as expected.

Screen-reader helpers now get the dragged choice from the drag data instead of parsing the id, and rows are keyed by promptId.

Existing tests couldn't catch the id collision because useDraggable is mocked globally. New tests now verify the ids passed to dnd-kit and cover the reducer case as well.

https://illuminate.atlassian.net/browse/PIE-965

…hoices behave independently PIE-965

dnd-kit keys its draggable registry, its isDragging flag and its drag transform off the id it is given, and match-list named a placed answer after the choice it held. With config.duplicates enabled the same choice can occupy several response areas, so all of those tiles registered under one id and collapsed into a single registry entry: they animated together, the last-registered tile's data resolved as the drag payload so the wrong response area changed, and unmounting any one of them deleted the entry the still-mounted siblings depended on, leaving a tile that was focusable but no longer draggable or reachable by the keyboard sensor. A placed answer is now identified by its response area; pool choices stay keyed by choice id, since the pool renders each choice once.

Also fills in a missing branch in placeAnswer: with duplicates enabled, moving a placed answer onto an occupied response area matched neither the swap branch, which requires duplicates to be off, nor the move branch, which requires an empty target, and was a silent no-op. It now takes the target and vacates its source, matching the choice-onto-occupied-target path.

The screen-reader label helpers recovered the dragged choice by regex-stripping the drag id, which the new id shape breaks; they read the tile's drag data instead. Rows are keyed by prompt id rather than index, now that each row owns a promptId-derived registration.

dnd-kit is mocked repo-wide in __mocks__/@dnd-kit/core.js with useDraggable stubbed to a constant, so no existing test could observe the collision. The new tests assert the ids handed to dnd-kit; 9 fail against the old id scheme and 2 against the old reducer.
@CarlaCostea
CarlaCostea merged commit 57ded61 into develop Sep 4, 2026
3 checks passed
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.

3 participants