Cart UX Improvements: Receipt-Style Layout and Clickable Card Images
2025-10-05
Cart UX Improvements: Receipt-Style Layout and Clickable Card Images
We've implemented two key UX improvements to the scan cart that make it more intuitive and functional for users browsing their scanned cards.
What Changed
1. Receipt-Style Vertical Expansion
Problem: Cart items were trapped in a fixed-height container with scrolling, making it hard to see your full cart at a glance.
Solution: Removed the maxHeight
constraint and overflowY: auto
styling. The cart now expands vertically like a receipt, showing all items without internal scrolling.
Impact:
- Better visibility: See your entire cart at once
- Natural scrolling: Page scrolls naturally instead of nested scroll containers
- Mobile-friendly: Easier to browse on phones without dealing with tiny scroll areas
- Receipt metaphor: Matches the mental model of a physical receipt that gets longer as you add items
2. Clickable Card Images with Correct Art Variant
Problem: Card images in the cart were purely decorative - clicking them did nothing. Users couldn't easily navigate to card detail pages to learn more about cards they'd scanned.
Solution:
- Wrapped card images in clickable links that navigate to
/cards/{oracle_id}?art={card_id}
- Passes the specific printing ID via
?art=
parameter so the card detail page shows the exact art variant - Added
stopPropagation()
to prevent event bubbling conflicts
Impact:
- Discovery workflow: Scan cards → browse cart → click to learn more about interesting finds
- Correct art display: Detail page shows the exact printing you scanned, not a random default
- Natural interaction: Images look clickable and behave as expected
- Context preservation: URL parameter ensures social shares/bookmarks preserve the specific art variant
Technical Implementation
Receipt-Style Layout
Before:
<div style={{
display: 'flex',
flexDirection: 'column',
gap: '1rem',
maxHeight: '360px', // ❌ Fixed height with internal scroll
overflowY: 'auto'
}}>
After:
<div style={{
display: 'flex',
flexDirection: 'column',
gap: '1rem' // ✅ Natural expansion, no scroll constraint
}}>
Also removed position: sticky
from the sidebar container so it flows naturally with page content instead of staying fixed at the top.
Clickable Card Images
Before:
<div style={{
width: '56px',
height: '80px',
borderRadius: '8px',
overflow: 'hidden',
background: '#eef2ff',
flexShrink: 0
}}>
<img src={item.localImage || item.image} alt={item.name} />
</div>
After:
const cardDetailUrl = item.oracle_id
? `/cards/${item.oracle_id}?art=${item.id}`
: `/cards/${item.id}`;
<a
href={cardDetailUrl}
style={{
width: '56px',
height: '80px',
borderRadius: '8px',
overflow: 'hidden',
background: '#eef2ff',
flexShrink: 0,
display: 'block',
textDecoration: 'none',
cursor: 'pointer'
}}
onClick={(e) => e.stopPropagation()}
>
<img src={item.localImage || item.image} alt={item.name} />
</a>
ID Structure: Cart items now store two IDs:
id
: The specific Scryfall print ID (unique to this exact printing)oracle_id
: The oracle ID shared across all printings of the same card
We use oracle_id
for the base URL (so all prints lead to the same card page) and pass the id
as the ?art=
parameter to feature that specific printing's artwork.
User Workflows Enabled
Trade Show Price Checking
- Scan multiple cards at vendor table
- Scroll through cart to see all scanned cards at once (receipt view)
- Click interesting cards to see all printings, legality, and detailed pricing
- Return to cart and continue scanning
Collection Discovery
- Scan cards from binder to track inventory
- Browse cart and spot cards you want to learn more about
- Click card images to explore similar cards, combos, deck ideas
- Add to cart from related cards shown on detail page
Budget Planning
- Scan wishlist cards from deck list
- See total price in expanded cart view
- Click cards to compare alternate printings and cheaper versions
- Update cart with budget alternatives
Mobile Experience
Both improvements particularly benefit mobile users:
- Receipt layout: No tiny scroll area - just natural page scrolling
- Clickable cards: Large touch targets (56×80px) easy to tap
- Context preservation: Back button returns to cart after viewing details
- Fast navigation: Jump between cart and detail pages without losing place
Performance Considerations
- No layout shift: Images maintain fixed size, no CLS when clicking
- Event delegation:
stopPropagation()
prevents conflicts with parent handlers - URL parameters: Lightweight art variant tracking without extra API calls
- Client-side navigation: Next.js Link behavior for instant page transitions
Implementation Notes
Why Remove Sticky Positioning?
Original cart used position: sticky
to keep it visible while scrolling the page. With receipt-style expansion, this creates UX problems:
- Long carts: Can't see bottom items without internal scrolling
- Layout conflicts: Sticky + scrolling parent = confusing behavior
- Mobile: Sticky sidebars don't work well on small screens
Solution: Let the cart flow naturally with page content. Users can scroll the entire page to see full cart.
Why Store Both IDs?
Cart items now explicitly store two separate IDs:
Print ID (id
):
- The specific Scryfall ID for this exact printing
- Example:
60b53d4e-56cb-4433-b8b5-5e67e5258dd5
- Unique to this set/collector number/finish combination
- Used for
?art=
parameter to show correct artwork
Oracle ID (oracle_id
):
- The shared identifier across all printings of the same card
- Example:
a1b2c3d4-e5f6-7890-abcd-ef1234567890
- Same for Secret Lair, regular set, promo versions, etc.
- Used for base URL so all prints lead to the same card page
This dual-ID approach ensures:
- All printings link to the same canonical card page (SEO-friendly)
- The correct artwork variant is featured when you arrive
- Users can explore all available printings from one page
Browser Compatibility
- Modern browsers: Full support for flexbox, anchor styling, URL parameters
- Event handling:
stopPropagation()
supported everywhere - Image rendering:
object-fit: cover
for proper aspect ratio - No polyfills needed: Pure CSS and standard DOM APIs
Future Enhancements
Hover Preview
- Quick peek: Hover card image to see larger preview without navigating
- Smart positioning: Preview appears beside cart, not covering it
- Touch alternative: Long-press on mobile for preview
Bulk Actions
- Select multiple: Checkboxes for batch operations
- Move to wishlist: Save interesting cards for later
- Export selected: Download subset of cart as CSV/TXT
Printing Comparison
- Side-by-side: Compare different printings from cart
- Price differences: Highlight best value options
- Set indicators: Show which sets have foil/showcase variants
Smart Grouping
- By deck: Organize cart items by commander/archetype
- By vendor: Group by which vendor had each card at show
- By price tier: Budget/mid/premium categories
Testing Checklist
- Cart expands vertically without height limit
- Page scrolls naturally with long carts
- Card images are clearly clickable (cursor, styling)
- Clicking images navigates to correct card detail page
-
?art=
parameter loads the correct printing variant - Back button returns to cart correctly
- Mobile: images tappable, no layout shift
- Mobile: scrolling smooth, no nested scroll confusion
- Social sharing card detail URLs preserve art variant
- No JavaScript errors in console
- No layout shift when clicking images
Related Features
Key Takeaway
Small UX improvements compound into better user experiences. Receipt-style layout removes cognitive friction (nested scrolling), while clickable images enable natural discovery workflows (scan → browse → explore). Both changes make the cart feel more responsive and intuitive without adding complexity.