Proposal H, Step 2 PR 2a: real candidate/version picker in the display rail - #96
Merged
WilfordGrimley merged 2 commits intoJul 18, 2026
Merged
Conversation
Wires the actual grid-selector machinery into the "Choose Image" accordion section, replacing its Step 1 stub: - Extracted GridSelectorModal.tsx's filtering/search state machine into useGridSelectorSearch.ts (a hook, parameterized by `active` instead of an inline `show` check) and its filters+results layout into GridSelectorResults.tsx (a `variant: "modal" | "embedded"` presentational component - "embedded" uses plain Col instead of OverflowCol, which would otherwise nest a second 100vh-relative scroll region inside the rail's own already-scrolling container). - GridSelectorModal.tsx itself now delegates to both rather than duplicating the logic - its own Modal/Header/Body/Footer JSX is otherwise unchanged, verified byte-identical in behavior by its full existing Playwright suite (GridSelectorModal[.Accessibility| .Mobile].spec.ts, 26 tests) plus CardSlot.spec.ts and DeckbuilderConfirmAffordance.spec.ts (11 tests) - all still passing. - DisplayPage.tsx's new ChooseImageSection mounts the same hook + component for the selected slot's search results, dispatching the same setSelectedImages action CardSlot.tsx's own grid selector uses - the sheet's thumbnail for that slot updates immediately (same Redux state, same PagePreview render path). Tests: 3 new/updated cases in tests/DisplayPage.spec.ts (selecting a candidate updates the sheet immediately; the embedded variant has no nested forced-scroll ancestor; the two Step 1 stub-text assertions this stub's removal made stale, updated to assert the real content). Full Jest suite (345 tests), tsc, eslint, and a real production build with the flag on (this task's own new standing verification bar) all pass.
…d the same bug CardRow's column-count props (xxl/xl/lg/md/sm/xs) key off *viewport* width via media queries, correct for the classic modal but wrong once the same grid is embedded in the display rail's ~150-250px results column - at a normal desktop viewport the viewport-driven breakpoints still picked 4-6 columns, squeezing each candidate card to a few px wide (effectively invisible, zero-width). CardResultSet/CardRow now take a variant prop; "embedded" pins a fixed 2-column layout that fits the rail regardless of viewport size. Separately, DisplayPage.spec.ts's new "Option N" assertions were missing the explicit Compressed-view toggle CardSlot.spec.ts already established as required precedent (Card.tsx doesn't render its header/title text at all under the default compressed=true view setting). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MHapYojTkT5wenrQwGbGYk
This was referenced Jul 18, 2026
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.
Description
Instrument parity, PR 2a of the Step 2 sequence for
docs/proposals/proposal-h-unified-display-page.md(behind
NEXT_PUBLIC_UNIFIED_DISPLAY_ENABLED, unmerged Step 1 shell from PR #87).The rail's "Choose Image" accordion section previously rendered a stub. This PR wires it up to the
real candidate/version-picker machinery, extracted out of
GridSelectorModal.tsxso the classicmodal and the new rail share one implementation instead of forking it:
useGridSelectorSearch.ts(new) —GridSelectorModal's entire filtering/sorting/search statemachine, extracted verbatim into a hook (
showrenamedactive).GridSelectorResults.tsx(new) — the filters-column + results-column body, extracted out of themodal. Takes a
variant: "modal" | "embedded"— "modal" wraps each column in the existingOverflowCol(unchanged behavior); "embedded" uses a plainColso the display rail's ownscroll container isn't fighting a second, nested one.
GridSelectorModal.tsx— refactored to consume both of the above. Its own behavior is unchangedand is proven so by its full existing Playwright suite (
GridSelectorModal.spec.ts,GridSelectorModalAccessibility.spec.ts,GridSelectorModalMobile.spec.ts— 26 tests), plusCardSlot.spec.tsandDeckbuilderConfirmAffordance.spec.ts, all passing unmodified.DisplayPage.tsx— "Choose Image" now renders aChooseImageSectionthat resolves the selectedslot's candidates the same way
CardSlot.tsxdoes and dispatches the samesetSelectedImagesaction on selection, so the sheet updates immediately.
CardResultSet.tsx— its result grid's column count (row-cols-*) is driven by viewport width,correct for the classic full-width modal but not for the rail's much narrower results column. Added
a
variantprop so "embedded" pins a fixed 2-column layout regardless of viewport size, instead ofsqueezing candidate cards down to a few px wide.
Checklist
pre-commitand installed the hooks withpre-commit installbefore creating any commits.DisplayPage.spec.tssuite (9 tests, incl. the embedded candidate grid's real selection flow and no-nested-scroll-region check).GridSelectorModal/GridSelectorModalAccessibility/GridSelectorModalMobile/CardSlot/DeckbuilderConfirmAffordancesuites (55 tests) to confirm zero behavior change to the classic modal.npx tsc --noEmitclean.npx jest— 345 tests passing.NEXT_PUBLIC_UNIFIED_DISPLAY_ENABLED=true npx next build— clean production build with the flag on (the standing verification bar added after PR Fix production build: RailProps.cardDocumentsByIdentifier needs | undefined #90's build failure).Per the Step 2 instructions: zero changes to the classic editor's/modal's behavior (verified above);
"After 2f: STOP" — steps 3/4 (inline export, switchover) are not part of this or any remaining Step 2 PR.
Generated by Claude Code