Skip to content

What's That: render one representative tile per illustration group - #730

Merged
WilfordGrimley merged 2 commits into
masterfrom
fix-illustration-one-representative
Aug 6, 2026
Merged

What's That: render one representative tile per illustration group#730
WilfordGrimley merged 2 commits into
masterfrom
fix-illustration-one-representative

Conversation

@WilfordGrimley

Copy link
Copy Markdown

Summary

When a What's That Card question is about which illustration a card uses, the grouped-tile render (illustrationGroups.map in QuestionFeed.tsx) rendered every candidate in the cluster as its own tile, while the tap handler (selectIllustrationGroup) already submits a single illustrationId for the whole group regardless of which member was tapped. A 4-printing group showed 4 near-identical images for a question with one answer; production data has groups as large as 9.

This renders exactly one representative tile per illustration group. The representative is chosen deterministically: the first group member with an artCropUrl set, falling back to the group's first member when none has one. This reuses a signal the render already applies per-tile (a tile's own image already prefers artCropUrl over the full scan), rather than inventing a new one, and the same input data always picks the same tile.

The submitted vote is unchanged: selectIllustrationGroup still receives the group's shared illustrationId (every member carries the same one), now sourced from the representative candidate instead of whichever member was tapped — the network payload is byte-for-byte identical to before. The group's own membership count (Same illustration - N printings) and data-illustration-id attribute are both untouched, so the cluster is still discoverable.

Separately, this investigated the issue's second symptom ("the first row of illustrations is hidden"). Live-browser reproduction (Playwright against the running app with a mock backend) showed the illustration group rendering clearly and visibly immediately below the "Filter by attribute" toggle, with its label, printing count, artist credit, and representative tile all present — it did not reproduce. No suppression, filter, or hiding logic exists in the render path, consistent with the prior static-code finding; this change does not touch anything that would affect visibility, and the symptom did not appear in this reproduction attempt.

Test plan

  • jest src/features/questionFeed/QuestionFeed.test.tsx — all 21 tests pass, including 2 new tests covering the art-crop-preferred representative pick (regardless of the crop's position in the group) and the fallback to the group's first member when no member has a crop
  • tsc --noEmit on the changed file — no new type errors (two pre-existing, unrelated errors from a missing generated asset and a dev-only module are present on master too)
  • Live-browser check (Playwright, mock backend): a 4-member illustration group renders exactly one tile (the art-crop member, not the first member), the group's "Same illustration - 4 printings" label and artist credit render normally and visibly, the ungrouped candidate renders separately and unaffected, and clicking the representative tile submits { illustrationId: <shared id> } to /2/submitIllustrationVote/ — identical to the pre-existing vote contract

The vote path (selectIllustrationGroup) already submits a single
illustrationId for the whole cluster, so the render side rendering
every member of the cluster showed the same artwork up to 9 times for
a question with one answer. Render only a representative tile per
group instead: prefer a member with an art crop (the same signal a
tile's own image already prefers), falling back to the group's first
member when none has one, so the pick is stable across renders of the
same data. The submitted illustrationId is unchanged - every group
member shares it.
…resentative-tile render

Three Level 2 illustration-grouping specs still asserted the retired
one-tile-per-group-member render: they expected candidateB (which shares
an illustration with candidateA but has no art crop) to get its own DOM
tile, both inside the group container and in the top-level candidate list.
The group now renders exactly one representative tile per cluster
(group.find((c) => c.artCropUrl) ?? group[0]), so a non-representative
member renders no tile of its own anywhere - it's represented through the
group's shared illustration vote, not silently dropped.

Renamed and rewrote the three affected titles to assert the new contract
directly (representative renders, non-representative member renders
nowhere, ungrouped candidates are unaffected) and added the matching
coverage-ack entries for the renames.
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.

1 participant