feat: Synchronize art crop display threshold to 200px and enforce square aspect ratio for art crop thumbnails in grid and stack views.

This commit is contained in:
2025-12-17 01:34:57 +01:00
parent 4ad0cd6fdc
commit ca2efb5cd7
5 changed files with 36 additions and 5 deletions

View File

@@ -61,3 +61,5 @@
- [Dynamic Art Cropping](./devlog/2025-12-17-024500_dynamic_art_cropping.md): Completed. Implemented automatic switching to full-art/art-crop images when card size is reduced below readability threshold.
- [Refined Preview Suppression](./devlog/2025-12-17-025000_refined_preview_suppression.md): Completed. Adjusted suppression threshold to 200px to better support Stack View's pop-up behavior.
- [Explicit Preview Suppression](./devlog/2025-12-17-025500_explicit_preview_suppression.md): Completed. Implemented strict `preventPreview` prop to enforce suppression logic reliably regardless of card overlap or DOM state.
- [Synchronized Display Boundaries](./devlog/2025-12-17-030000_synchronized_boundaries.md): Completed. Aligned "Art Crop" and "Preview Suppression" thresholds to 200px (50% slider value) for a unified UI behavior.
- [Squared Art Crops](./devlog/2025-12-17-030500_squared_art_crops.md): Completed. Enforced square aspect ratio for art-crop thumbnails to optimize visual density and stacking.

View File

@@ -0,0 +1,13 @@
# Synchronized Display Boundaries
## Objective
Harmonize the "Full Art" visualization mode with the specific behavior of the slider and preview suppression logic.
## Changes
- **Threshold Update**: Shifted the trigger point for Art Crop visualization (full art thumbnails) from `170px` to **`200px`**.
- This corresponds to exactly **50% of the slider range** (100px-300px), creating a predictable user interface boundary.
- **< 200px**: Cards display as **Art Crops (Full Art)** because text would be illegible. **Hover Preview is Enabled** to show the card details.
- **>= 200px**: Cards display as **Standard Scryfall Images** (with borders/text) because text is legible. **Hover Preview is Disabled** to prevent redundancy, as the card itself acts as the reference.
## Result
A unified "Pivot Point" at 200px. Sliding left gives you a dense, artistic mosaic with helpful popups. Sliding right gives you a readable, "tabletop" view with direct card interaction and no popup clutter.

View File

@@ -0,0 +1,16 @@
# Squared Art Crops
## Objective
Optimize the "Full Art" display mode by switching from a rectangular card ratio to a square ratio. This focuses the view on the artwork itself (which is typically landscape/square-ish in crops) and provides a more compact, tile-like aesthetic for small thumbnails.
## Changes
- **Grid View (`PackCard`)**:
- Dynamically switches CSS classes: uses `aspect-square` when in Art Crop mode (<200px), and `aspect-[2.5/3.5]` (standard card ratio) otherwise.
- Creates a uniform grid of square tiles for the visual overview.
- **Stack View (`StackView`)**:
- Dynamically adjusts inline styles:
- `aspectRatio`: Switches between `'1/1'` and `'2.5/3.5'`.
- `marginBottom` (for stacking overlap): Adjusted from `-125%` (for tall rectangles) to `-85%` (for squares) to maintain a consistent visible "header strip" for cards underneath.
## Result
When you slide the size down, the cards now morph into neat square tiles. This maximizes the art visibility within the small space and makes the "mosaic" feel even more deliberate and organized.

View File

@@ -100,14 +100,14 @@ export const PackCard: React.FC<PackCardProps> = ({ pack, viewMode, cardWidth =
{viewMode === 'grid' && (
<div className="flex flex-wrap gap-3">
{pack.cards.map((card) => {
const useArtCrop = cardWidth < 170 && !!card.imageArtCrop;
const useArtCrop = cardWidth < 200 && !!card.imageArtCrop;
const displayImage = useArtCrop ? card.imageArtCrop : card.image;
return (
<CardHoverWrapper key={card.id} card={card} preventPreview={cardWidth >= 200}>
<div style={{ width: cardWidth }} className="relative group bg-slate-900 rounded-lg shrink-0">
{/* Visual Card */}
<div className={`relative aspect-[2.5/3.5] overflow-hidden rounded-lg shadow-xl border transition-all duration-200 group-hover:ring-2 group-hover:ring-purple-400 group-hover:shadow-purple-500/30 cursor-pointer ${isFoil(card) ? 'border-purple-400 shadow-purple-500/20' : 'border-slate-800'}`}>
<div className={`relative ${useArtCrop ? 'aspect-square' : 'aspect-[2.5/3.5]'} overflow-hidden rounded-lg shadow-xl border transition-all duration-200 group-hover:ring-2 group-hover:ring-purple-400 group-hover:shadow-purple-500/30 cursor-pointer ${isFoil(card) ? 'border-purple-400 shadow-purple-500/20' : 'border-slate-800'}`}>
{isFoil(card) && <FoilOverlay />}
{isFoil(card) && <div className="absolute top-1 right-1 z-30 text-[10px] font-bold text-white bg-purple-600/80 px-1 rounded backdrop-blur-sm">FOIL</div>}

View File

@@ -73,7 +73,7 @@ export const StackView: React.FC<StackViewProps> = ({ cards, cardWidth = 150 })
// Margin calculation: Negative margin to pull up next cards.
// To show a "strip" of say 35px at the top of each card.
const isLast = index === catCards.length - 1;
const useArtCrop = cardWidth < 170 && !!card.imageArtCrop;
const useArtCrop = cardWidth < 200 && !!card.imageArtCrop;
const displayImage = useArtCrop ? card.imageArtCrop : card.image;
return (
@@ -83,8 +83,8 @@ export const StackView: React.FC<StackViewProps> = ({ cards, cardWidth = 150 })
style={{
// Aspect ratio is maintained by image or div dimensions
// With overlap, we just render them one after another with negative margin
marginBottom: isLast ? '0' : '-125%', // Negative margin to show header
aspectRatio: '2.5/3.5'
marginBottom: isLast ? '0' : (useArtCrop ? '-85%' : '-125%'), // Negative margin to show header. Square cards need less negative margin.
aspectRatio: useArtCrop ? '1/1' : '2.5/3.5'
}}
>
<img src={displayImage} alt={card.name} className="w-full h-full object-cover" />