Skip to content

Staggered Triple Stack Visualization#212

Open
amorris13 wants to merge 3 commits into
masterfrom
triple-stack-visual-update-5173821560565866598
Open

Staggered Triple Stack Visualization#212
amorris13 wants to merge 3 commits into
masterfrom
triple-stack-visual-update-5173821560565866598

Conversation

@amorris13

@amorris13 amorris13 commented Mar 24, 2026

Copy link
Copy Markdown
Owner

Updated the visual appearance of card stacks in the game to include a 10% horizontal offset and a 45% vertical overlap, matching the app's logo and providing a more realistic "stack" look. Adjusted TripleStackView and FoundTriplesView to support these changes while maintaining proper layout and animation targets.


PR created automatically by Jules for task 5173821560565866598 started by @amorris13

Summary by CodeRabbit

  • Style
    • Updated triple-card layouts to add a horizontal stacking offset alongside the existing vertical offset, enhancing layered appearance.
    • Adjusted card sizing, outlines/clipping, animation targets, and highlight/placeholder bounds so cards align, animate, and render correctly with the new horizontal displacement.
    • Added per-card horizontal margins and dynamic row overlap so explanation views lay out responsively during measurement.

…d overlap

Modified `TripleStackView` and `FoundTriplesView` to implement a 10%
horizontal offset between cards in a stack and increased the vertical
overlap to 45% (a 10% increase). This change makes the triple stack
visuals more closely resemble the app's logo and look more like a
physical stack of cards.

Updated dimension calculations, drawing logic, and touch bounds to
ensure consistent layout and animations across the app. Verified the
changes via Roborazzi screenshots and existing unit tests.

Co-authored-by: amorris13 <4523811+amorris13@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c192f21f-a4e0-4bdd-902c-0de1fd813e21

📥 Commits

Reviewing files that changed from the base of the PR and between 7e51a9b and 27d1d63.

⛔ Files ignored due to path filters (6)
  • app/src/test/screenshots/beginner_mode_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/beginner_mode_light.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/help_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/help_light.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java

📝 Walkthrough

Walkthrough

Adds horizontal stack displacement to triple card layouts: card width, stack horizontal displacement, measurement, rendering transforms, animation target bounds, and outline/clipping are updated across three view classes to position each card with an i * horizontal offset and adjusted vertical overlap.

Changes

Cohort / File(s) Summary
Stacking & bounds logic
app/src/main/java/com/antsapps/triples/views/FoundTriplesView.java, app/src/main/java/com/antsapps/triples/views/TripleStackView.java
Introduces STACK_HORIZ_DISPLACEMENT_PERCENT / mStackHorizDisplacement. Recomputes mCardWidth during measure to account for horizontal displacement, applies per-card horizontal offset i * mStackHorizDisplacement to computed card bounds, rendering translations, animation target bounds, and outline/clip geometry so total width = mCardWidth + 2*mStackHorizDisplacement.
Explanation layout margins & measurement
app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java
Allocates/retains three LinearLayout rows (mCardRows), moves card positioning into onMeasure(), computes per-cell width and horizontal displacement from measured width, updates each card's LayoutParams (left/right margins) and sets row topMargin for vertical overlap rather than a one-time static offset.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nudge each card a little to the side,
They tilt and tuck in a three-card tide.
Widths re-counted, margins softly spread,
A neat little stack where once they were spread. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Staggered Triple Stack Visualization' accurately summarizes the main change—introducing a staggered (horizontally offset and vertically overlapped) visual effect to card stack layouts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch triple-stack-visual-update-5173821560565866598

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
app/src/main/java/com/antsapps/triples/views/TripleStackView.java (1)

90-92: A small stack-bounds helper would trim repeated geometry math.

mCardWidth + 2 * mStackHorizDisplacement and the same RectF edges are rebuilt in the outline, highlight, and placeholder paths. Pulling that into one helper would make the next stack-shape tweak a little safer.

Also applies to: 207-228

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/antsapps/triples/views/TripleStackView.java` around
lines 90 - 92, Extract the repeated geometry math into a small helper on
TripleStackView (e.g., getStackBounds() or computeStackRect()) that uses
mPadding, mCardWidth, mStackHorizDisplacement and totalHeight to return a RectF
(or the left/top/right/bottom values) representing the stack rectangle; then
replace the duplicated expressions (mCardWidth + 2 * mStackHorizDisplacement and
the repeated RectF edges used in outline.setRoundRect, the highlight path, and
the placeholder path) with calls to that helper so all three places reuse the
same computed bounds.
app/src/main/java/com/antsapps/triples/views/FoundTriplesView.java (1)

202-208: Consider sharing the stack geometry calculation.

FoundTriplesView now copies the same card-width and displacement math that TripleStackView.updateDimensions() already owns. Centralizing that logic would reduce the chance of parent-computed animation targets drifting from the child’s actual render geometry on the next visual tweak.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/antsapps/triples/views/FoundTriplesView.java` around
lines 202 - 208, FoundTriplesView duplicates the card/displacement math from
TripleStackView.updateDimensions(), causing drift risk; replace the inline
calculations for mCardWidth, mCardHeight, mStackDisplacement and
mStackHorizDisplacement with a call to a shared helper on TripleStackView (e.g.,
add a public static method like TripleStackView.calculateStackGeometry(int
slotWidth, int padding) or expose an accessor that returns computed
width/height/displacements) and use its returned values (based on CARD ratios,
TripleStackView.STACK_DISPLACEMENT_PERCENT, STACK_HORIZ_DISPLACEMENT_PERCENT and
CardView.HEIGHT_OVER_WIDTH) instead of recomputing from mSlotWidth and mPadding
in FoundTriplesView so both parent and child use the same source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/com/antsapps/triples/views/FoundTriplesView.java`:
- Around line 202-208: FoundTriplesView duplicates the card/displacement math
from TripleStackView.updateDimensions(), causing drift risk; replace the inline
calculations for mCardWidth, mCardHeight, mStackDisplacement and
mStackHorizDisplacement with a call to a shared helper on TripleStackView (e.g.,
add a public static method like TripleStackView.calculateStackGeometry(int
slotWidth, int padding) or expose an accessor that returns computed
width/height/displacements) and use its returned values (based on CARD ratios,
TripleStackView.STACK_DISPLACEMENT_PERCENT, STACK_HORIZ_DISPLACEMENT_PERCENT and
CardView.HEIGHT_OVER_WIDTH) instead of recomputing from mSlotWidth and mPadding
in FoundTriplesView so both parent and child use the same source of truth.

In `@app/src/main/java/com/antsapps/triples/views/TripleStackView.java`:
- Around line 90-92: Extract the repeated geometry math into a small helper on
TripleStackView (e.g., getStackBounds() or computeStackRect()) that uses
mPadding, mCardWidth, mStackHorizDisplacement and totalHeight to return a RectF
(or the left/top/right/bottom values) representing the stack rectangle; then
replace the duplicated expressions (mCardWidth + 2 * mStackHorizDisplacement and
the repeated RectF edges used in outline.setRoundRect, the highlight path, and
the placeholder path) with calls to that helper so all three places reuse the
same computed bounds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 358267f5-58ae-4b13-a740-701b83d2d599

📥 Commits

Reviewing files that changed from the base of the PR and between e5ceff7 and 28f8fc2.

⛔ Files ignored due to path filters (35)
  • app/src/test/screenshots/arcade_game_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/arcade_game_light.png is excluded by !**/*.png
  • app/src/test/screenshots/beginner_mode_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/beginner_mode_light.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_light.png is excluded by !**/*.png
  • app/src/test/screenshots/daily_game_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/daily_game_light.png is excluded by !**/*.png
  • app/src/test/screenshots/help_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/help_light.png is excluded by !**/*.png
  • app/src/test/screenshots/incorrect_triples_snackbar.png is excluded by !**/*.png
  • app/src/test/screenshots/main_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/main_light.png is excluded by !**/*.png
  • app/src/test/screenshots/settings_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/settings_light.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_arcade_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_arcade_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_arcade_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_arcade_light.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_light.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_partial_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/statistics_classic_partial_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/view_board_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/view_board_light.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_hint_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_hint_light.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_hint_selected_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_hint_selected_light.png is excluded by !**/*.png
  • app/src/test/screenshots/zen_game_light.png is excluded by !**/*.png
📒 Files selected for processing (2)
  • app/src/main/java/com/antsapps/triples/views/FoundTriplesView.java
  • app/src/main/java/com/antsapps/triples/views/TripleStackView.java

Implemented a 10% horizontal displacement in `TripleStackView` and
`FoundTriplesView` to mimic the app logo and create a more natural stack
appearance. Also added horizontal displacement to cards in the
`TripleExplanationView` for visual consistency. Reverted the vertical
overlap changes, maintaining the original 65% displacement (35% overlap).

Updated layout logic and bounds calculations to ensure correct sizing and
animations. Verified the changes with updated Roborazzi screenshot tests.

Co-authored-by: amorris13 <4523811+amorris13@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java (1)

81-89: Fixed dp margins may not match the claimed "10% of card width" across screen sizes.

The comment states this mimics a "10% of card width" shift, but the implementation uses fixed 3dp increments. In TripleStackView, the horizontal displacement is calculated dynamically as mCardWidth * 0.10f. Depending on the actual card width in this view, 3dp may not equal 10% of the card width, potentially causing visual inconsistency between the explanation view and the stack view on different screen densities or sizes.

Consider calculating the margin dynamically based on the card's measured width, similar to how TripleStackView calculates mStackHorizDisplacement.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java`
around lines 81 - 89, The fixed 3dp margins in TripleExplanationView don't
reflect the "10% of card width" shift and can diverge across devices; change the
margin calculation to compute horizontal displacement from the actual measured
card width (like TripleStackView's mStackHorizDisplacement = cardWidth * 0.10f)
instead of dpToPx(3). After the card views are measured (e.g., in
onLayout/onMeasure or by posting a Runnable after layout), read the card width
(from mCardViews[i].getMeasuredWidth() or the container width divided by cell
count), compute int horiz = Math.round(cardWidth * 0.10f), and set
cardParams.leftMargin/rightMargin using horiz * i and horiz * (2 - i) before
calling mCardViews[i].setLayoutParams(cardParams); keep using dpToPx only for
true fixed paddings, not for this proportional offset.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java`:
- Around line 81-89: The fixed 3dp margins in TripleExplanationView don't
reflect the "10% of card width" shift and can diverge across devices; change the
margin calculation to compute horizontal displacement from the actual measured
card width (like TripleStackView's mStackHorizDisplacement = cardWidth * 0.10f)
instead of dpToPx(3). After the card views are measured (e.g., in
onLayout/onMeasure or by posting a Runnable after layout), read the card width
(from mCardViews[i].getMeasuredWidth() or the container width divided by cell
count), compute int horiz = Math.round(cardWidth * 0.10f), and set
cardParams.leftMargin/rightMargin using horiz * i and horiz * (2 - i) before
calling mCardViews[i].setLayoutParams(cardParams); keep using dpToPx only for
true fixed paddings, not for this proportional offset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 837e20d0-dd55-4764-9254-2b30d6f3c182

📥 Commits

Reviewing files that changed from the base of the PR and between 28f8fc2 and 7e51a9b.

⛔ Files ignored due to path filters (10)
  • app/src/test/screenshots/beginner_mode_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/beginner_mode_light.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/classic_game_analysis_light.png is excluded by !**/*.png
  • app/src/test/screenshots/daily_game_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/daily_game_light.png is excluded by !**/*.png
  • app/src/test/screenshots/help_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/help_light.png is excluded by !**/*.png
  • app/src/test/screenshots/view_board_dark.png is excluded by !**/*.png
  • app/src/test/screenshots/view_board_light.png is excluded by !**/*.png
📒 Files selected for processing (2)
  • app/src/main/java/com/antsapps/triples/views/TripleExplanationView.java
  • app/src/main/java/com/antsapps/triples/views/TripleStackView.java

// Since the card cell takes 1/5th of the row width, a 10% shift of the card is
// effectively a shift of 0.1 * (1/5) = 2% of the total row width.
// We apply this using margins to avoid drawing outside the cell bounds.
cardParams.leftMargin = dpToPx(i * 3);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Ideally this 3 (and the -13 for the topMargin above) would instead be calculated based on the measured width of the card, rather than just hardcoded. Is that possible?

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.

I've updated TripleExplanationView.java to calculate these margins dynamically in onMeasure. The horizontal and vertical displacements now use the constants from TripleStackView and the measured width of the view, ensuring visual consistency without hardcoded values.

Updated `TripleExplanationView.java` to calculate horizontal and
vertical margins dynamically in `onMeasure` using the card width and
constants from `TripleStackView`. This ensures the staggered effect is
consistent across different screen sizes and avoids hardcoded pixel
values. Also fixed a missing import for `CardView` and verified the
visuals with updated Roborazzi screenshots.

Co-authored-by: amorris13 <4523811+amorris13@users.noreply.github.com>
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