Skip to content

Fix card hover preview interactions - #7043

Merged
matthewevans merged 2 commits into
mainfrom
agent/modal-hover-preview-followup
Aug 6, 2026
Merged

Fix card hover preview interactions#7043
matthewevans merged 2 commits into
mainfrom
agent/modal-hover-preview-followup

Conversation

@matthewevans

@matthewevans matthewevans commented Aug 5, 2026

Copy link
Copy Markdown
Member

Fixes modal card-preview placement and incorporates the outstanding hover-preview review feedback from the now-merged #7040.

  • Dock card previews to the side within dialogs and compact the counter-distribution modal.
  • Preserve complete printing-aware hover metadata through deck-builder components.
  • Add touch long-press previews in Limited deck builder without moving cards.

Validation: formatting, Clippy, parser gates, 619 Oracle-parser tests, and 2,020 phase-AI tests passed. Card-data generation could not run because data/mtgjson/AtomicCards.json is absent locally.

Summary by CodeRabbit

  • New Features
    • Card previews opened from dialogs and choice screens now dock consistently to the side.
    • Touch users can long-press cards in limited deck building to preview them without adding them.
    • Card previews now preserve printing details for more accurate results across deck-building views.
  • Bug Fixes
    • Improved preview behavior when switching between cursor-based and side-docked placement.
    • Side-docked modal previews now use a more suitable display width.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@matthewevans, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 5 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 69caf80c-4879-4095-aa55-f7ddda2ae01b

📥 Commits

Reviewing files that changed from the base of the PR and between 50efcee and af539f7.

📒 Files selected for processing (6)
  • client/src/components/deck-builder/CommanderPanel.tsx
  • client/src/components/deck-builder/DeckList.tsx
  • client/src/components/draft/__tests__/LimitedDeckBuilder.test.tsx
  • client/src/hooks/__tests__/useInspectHoverProps.test.tsx
  • client/src/hooks/useInspectHoverProps.ts
  • client/src/hooks/useLongPress.ts
📝 Walkthrough

Walkthrough

The change adds runtime preview placement state, detects side-docked modal containers, and updates preview rendering. Deck-builder hover callbacks now pass structured card metadata. Draft cards support touch long-press previews without triggering card addition.

Changes

Card preview placement

Layer / File(s) Summary
Preview placement state and detection
client/src/stores/uiStore.ts, client/src/hooks/useInspectHoverProps.ts
The UI store records "cursor" or "side" placement. Hover and long-press inspection passes the detected placement and resets it when previews close.
Side-docked preview rendering
client/src/components/card/GameCardPreview.tsx, client/src/components/modal/*, client/src/components/card/__tests__/GameCardPreview.test.tsx, client/src/hooks/__tests__/useInspectHoverProps.test.tsx
GameCardPreview docks previews when the runtime placement or side preference is active. Modal containers identify side-docked layouts, and tests cover placement behavior.
Structured deck-builder hover data
client/src/components/deck-builder/*, client/src/pages/DeckBuilderPage.tsx, client/src/components/deck-builder/__tests__/CardEntryRow.test.tsx
Deck-builder hover callbacks use CardHoverHandler and pass card names, Scryfall IDs, and source printings through CardHoverInfo.
Draft card long-press previews
client/src/components/draft/LimitedDeckBuilder.tsx, client/src/components/draft/__tests__/LimitedDeckBuilder.test.tsx
Touch long press opens a preview. The following synthetic click does not add the card to the deck.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ModalContainer
  participant useInspectHoverProps
  participant uiStore
  participant GameCardPreview
  ModalContainer->>useInspectHoverProps: identify side-docked preview context
  useInspectHoverProps->>uiStore: inspectObject(card, timing, "side")
  uiStore->>GameCardPreview: publish previewPlacement
  GameCardPreview->>GameCardPreview: render side-docked preview
Loading

Possibly related PRs

  • phase-rs/phase#7040: Both changes update hover-preview behavior and structured card hover data.
  • phase-rs/phase#6680: Both changes modify useInspectHoverProps and its hover and long-press tests.
  • phase-rs/phase#6239: Both changes modify GameCardPreview.tsx and card preview positioning behavior.

Suggested labels: bug, feature

Suggested reviewers: kiannidev

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the pull request's main changes to card hover preview behavior.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/modal-hover-preview-followup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matthewevans
matthewevans marked this pull request as ready for review August 5, 2026 20:47
@matthewevans
matthewevans force-pushed the agent/modal-hover-preview-followup branch from 2474cf9 to 50efcee Compare August 5, 2026 23:06

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
client/src/components/deck-builder/CommanderPanel.tsx (1)

96-210: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve the cached Scryfall ID for commander previews.

These name-only payloads discard the printing identity available in cardDataCache. The preview can then resolve a different printing than the deck-builder card record.

  • client/src/components/deck-builder/CommanderPanel.tsx#L96-L210: Build each hover payload with name and cardDataCache.get(name)?.id.
  • client/src/components/deck-builder/DeckList.tsx#L256-L257: Build the commander hover payload with name and cardDataCache.get(name)?.id.

As per path instructions, “propagate complete printing-aware hover data consistently through all deck-builder components.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/deck-builder/CommanderPanel.tsx` around lines 96 - 210,
Preserve printing-aware preview data by updating every mouseHoverPreview call in
client/src/components/deck-builder/CommanderPanel.tsx lines 96-210 to pass name
and cardDataCache.get(name)?.id, including commander, signature spell, and
companion entries. Apply the same payload change to the commander hover preview
in client/src/components/deck-builder/DeckList.tsx lines 256-257, using the
existing cardDataCache.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/components/deck-builder/hoverPreview.ts`:
- Around line 2-4: Update the CommanderPanel.tsx and DeckList.tsx callers of
mouseHoverPreview to build CardHoverInfo from the complete underlying deck/card
record, preserving scryfallId and sourcePrinting when available instead of
passing only name. Keep deck-builder hover data complete and printing-aware, and
do not rely on optional CardHoverInfo fields to mask missing metadata.

In `@client/src/components/draft/LimitedDeckBuilder.tsx`:
- Around line 61-68: Update the useLongPress implementation and the handleClick
path in LimitedDeckBuilder so firedRef is cleared when the pointer gesture ends
or is canceled, while retaining one-shot suppression for the synthetic click
generated by a completed long press. Add a regression test covering cancellation
without a click followed by keyboard activation, ensuring the keyboard
activation invokes onClick.

In `@client/src/hooks/useInspectHoverProps.ts`:
- Around line 77-83: Update the onPointerDown handler in useInspectHoverProps to
reject non-primary pointers and non-appropriate buttons before assigning
pressedIdRef, pressedPlacementRef, or calling armLongPress, matching the guards
used by useLongPress. Preserve the active first touch so a secondary touch
cannot retarget the armed preview, and add a colocated regression test covering
two simultaneous touches.

---

Outside diff comments:
In `@client/src/components/deck-builder/CommanderPanel.tsx`:
- Around line 96-210: Preserve printing-aware preview data by updating every
mouseHoverPreview call in client/src/components/deck-builder/CommanderPanel.tsx
lines 96-210 to pass name and cardDataCache.get(name)?.id, including commander,
signature spell, and companion entries. Apply the same payload change to the
commander hover preview in client/src/components/deck-builder/DeckList.tsx lines
256-257, using the existing cardDataCache.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d8b20299-5862-424b-bf60-d0731dac32cd

📥 Commits

Reviewing files that changed from the base of the PR and between c44a451 and 50efcee.

📒 Files selected for processing (21)
  • client/src/components/card/GameCardPreview.tsx
  • client/src/components/card/__tests__/GameCardPreview.test.tsx
  • client/src/components/deck-builder/CardEntryRow.tsx
  • client/src/components/deck-builder/CardGrid.tsx
  • client/src/components/deck-builder/CommanderPanel.tsx
  • client/src/components/deck-builder/DeckBuilder.tsx
  • client/src/components/deck-builder/DeckList.tsx
  • client/src/components/deck-builder/DeckStack.tsx
  • client/src/components/deck-builder/MoveList.tsx
  • client/src/components/deck-builder/PrintingPickerModal.tsx
  • client/src/components/deck-builder/__tests__/CardEntryRow.test.tsx
  • client/src/components/deck-builder/hoverPreview.ts
  • client/src/components/draft/LimitedDeckBuilder.tsx
  • client/src/components/draft/__tests__/LimitedDeckBuilder.test.tsx
  • client/src/components/modal/ChoiceOverlay.tsx
  • client/src/components/modal/DialogShell.tsx
  • client/src/components/modal/DistributeAmongModal.tsx
  • client/src/hooks/__tests__/useInspectHoverProps.test.tsx
  • client/src/hooks/useInspectHoverProps.ts
  • client/src/pages/DeckBuilderPage.tsx
  • client/src/stores/uiStore.ts

Comment on lines +2 to +4
import type { CardHoverInfo } from "../card/CardPreview";

export type CardHoverHandler = (card: CardHoverInfo | null) => void;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Preserve complete hover metadata at every caller.

CardHoverInfo still allows scryfallId and sourcePrinting to be omitted. The provided CommanderPanel.tsx and DeckList.tsx callers pass { name }, so they discard printing metadata when it is available from the underlying card record. Those previews cannot remain printing-aware.

Update the callers to construct CardHoverInfo from the complete deck or card record before calling mouseHoverPreview. Do not use the optional fields to hide a missing cross-component contract.

As per path instructions, deck-builder hover data must remain complete and printing-aware.

Also applies to: 26-32

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/deck-builder/hoverPreview.ts` around lines 2 - 4,
Update the CommanderPanel.tsx and DeckList.tsx callers of mouseHoverPreview to
build CardHoverInfo from the complete underlying deck/card record, preserving
scryfallId and sourcePrinting when available instead of passing only name. Keep
deck-builder hover data complete and printing-aware, and do not rely on optional
CardHoverInfo fields to mask missing metadata.

Source: Path instructions

Comment on lines +61 to +68
const { handlers, firedRef } = useLongPress(() => onHover(hoverInfo));

const handleClick = () => {
if (firedRef.current) {
firedRef.current = false;
return;
}
onClick();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope firedRef to the completed pointer gesture.

useLongPress leaves firedRef.current set after the timer fires. Its pointer-cancel and pointer-up paths do not reset this flag. If no synthetic click follows, this handler suppresses the next keyboard or programmatic activation because no new pointerdown resets the flag. Make the suppression one-shot and expire it when the gesture is canceled. Add a regression test for cancellation without a click followed by keyboard activation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/draft/LimitedDeckBuilder.tsx` around lines 61 - 68,
Update the useLongPress implementation and the handleClick path in
LimitedDeckBuilder so firedRef is cleared when the pointer gesture ends or is
canceled, while retaining one-shot suppression for the synthetic click generated
by a completed long press. Add a regression test covering cancellation without a
click followed by keyboard activation, ensuring the keyboard activation invokes
onClick.

Comment thread client/src/hooks/useInspectHoverProps.ts
@matthewevans
matthewevans merged commit 76fc553 into main Aug 6, 2026
14 checks passed
@matthewevans
matthewevans deleted the agent/modal-hover-preview-followup branch August 6, 2026 00:02
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