feat: rename Deck to Library and implement tap-to-preview for cards in Deck Builder on touch devices.

This commit is contained in:
2025-12-18 01:26:07 +01:00
parent d550bc3d04
commit 0ca29622ef
3 changed files with 46 additions and 7 deletions

View File

@@ -96,3 +96,4 @@
- [Create Favicon](./devlog/2025-12-18-005739_create_favicon.md): Completed. Generated and integrated a new application favicon. - [Create Favicon](./devlog/2025-12-18-005739_create_favicon.md): Completed. Generated and integrated a new application favicon.
- [Mobile Touch Preview](./devlog/2025-12-18-012500_mobile_touch_preview.md): Completed. Updated card preview logic to disable hover and enable long-press on touch devices, improving usability on tablets and mobile. - [Mobile Touch Preview](./devlog/2025-12-18-012500_mobile_touch_preview.md): Completed. Updated card preview logic to disable hover and enable long-press on touch devices, improving usability on tablets and mobile.
- [Minimize Slider Defaults](./devlog/2025-12-18-013000_minimize_slider_defaults.md): Completed. Set default card size settings to their minimum values across Cube Manager, Draft View, and Deck Builder. - [Minimize Slider Defaults](./devlog/2025-12-18-013000_minimize_slider_defaults.md): Completed. Set default card size settings to their minimum values across Cube Manager, Draft View, and Deck Builder.
- [Deck Builder Touch Interaction](./devlog/2025-12-18-014500_deck_builder_touch.md): Completed. Renamed "Deck" to "Library" and implemented tap-to-preview logic on touch devices, disabling tap-to-move.

View File

@@ -0,0 +1,20 @@
# Work Plan - Deck Builder Touch Interaction Updates
## Request
1. Change "Deck" zone name to "Library" in the UI.
2. Update touch interaction logic in Deck Builder:
- Tap (1 finger) should NOT move the card (add/remove).
- Tap (1 finger) should show the Card Preview (like in Draft Pick).
- Drag and Drop remains the method to move cards on touch devices.
## Changes
- **DeckBuilderView.tsx**:
- Replaced display text "Deck" with "Library" in headers and empty state messages.
- Updated `ListItem`, `DeckCardItem`, and `StackView` `onClick` handlers.
- Implemented `window.matchMedia('(pointer: coarse)')` check to toggle behavior:
- **Touch**: Tap -> `onHover(card)` (Preview)
- **Mouse**: Click -> `onCardClick(card)` (Add/Remove)
## Verification
- Verified code changes apply to all view modes (List, Grid, Stack).
- Verified drag-and-drop mechanics were not altered (handled by dnd-kit wrappers).

View File

@@ -91,7 +91,13 @@ const ListItem: React.FC<{ card: DraftCard; onClick?: () => void; onHover?: (c:
} }
}; };
const { onTouchStart, onTouchEnd, onTouchMove, onClick: handleTouchClick } = useCardTouch(onHover || (() => { }), onClick || (() => { }), card); const { onTouchStart, onTouchEnd, onTouchMove, onClick: handleTouchClick } = useCardTouch(onHover || (() => { }), () => {
if (window.matchMedia('(pointer: coarse)').matches) {
if (onHover) onHover(card);
} else {
if (onClick) onClick();
}
}, card);
return ( return (
<div <div
@@ -159,7 +165,13 @@ const CardsDisplay: React.FC<{
<StackView <StackView
cards={cards.map(normalizeCard)} cards={cards.map(normalizeCard)}
cardWidth={cardWidth} cardWidth={cardWidth}
onCardClick={(c) => onCardClick(c)} onCardClick={(c) => {
if (window.matchMedia('(pointer: coarse)').matches) {
onHover(c);
} else {
onCardClick(c);
}
}}
onHover={(c) => onHover(c)} onHover={(c) => onHover(c)}
disableHoverPreview={true} disableHoverPreview={true}
/> />
@@ -564,10 +576,10 @@ export const DeckBuilderView: React.FC<DeckBuilderViewProps> = ({ initialPool, a
{/* Deck Column */} {/* Deck Column */}
<DroppableZone id="deck-zone" className="flex-1 flex flex-col min-w-0 bg-slate-900/50"> <DroppableZone id="deck-zone" className="flex-1 flex flex-col min-w-0 bg-slate-900/50">
<div className="p-3 border-b border-slate-800 font-bold text-slate-400 uppercase text-xs flex justify-between"> <div className="p-3 border-b border-slate-800 font-bold text-slate-400 uppercase text-xs flex justify-between">
<span>Deck ({deck.length})</span> <span>Library ({deck.length})</span>
</div> </div>
<div className="flex-1 overflow-auto p-2 custom-scrollbar"> <div className="flex-1 overflow-auto p-2 custom-scrollbar">
<CardsDisplay cards={deck} viewMode={viewMode} cardWidth={cardWidth} onCardClick={removeFromDeck} onHover={setHoveredCard} emptyMessage="Your Deck is Empty" source="deck" /> <CardsDisplay cards={deck} viewMode={viewMode} cardWidth={cardWidth} onCardClick={removeFromDeck} onHover={setHoveredCard} emptyMessage="Your Library is Empty" source="deck" />
</div> </div>
</DroppableZone> </DroppableZone>
</div> </div>
@@ -586,10 +598,10 @@ export const DeckBuilderView: React.FC<DeckBuilderViewProps> = ({ initialPool, a
{/* Bottom: Deck */} {/* Bottom: Deck */}
<DroppableZone id="deck-zone" className="h-[40%] flex flex-col min-h-0 bg-slate-900/50"> <DroppableZone id="deck-zone" className="h-[40%] flex flex-col min-h-0 bg-slate-900/50">
<div className="p-2 border-b border-slate-800 font-bold text-slate-400 uppercase text-xs flex justify-between shrink-0"> <div className="p-2 border-b border-slate-800 font-bold text-slate-400 uppercase text-xs flex justify-between shrink-0">
<span>Deck ({deck.length})</span> <span>Library ({deck.length})</span>
</div> </div>
<div className="flex-1 overflow-auto p-2 custom-scrollbar"> <div className="flex-1 overflow-auto p-2 custom-scrollbar">
<CardsDisplay cards={deck} viewMode={viewMode} cardWidth={cardWidth} onCardClick={removeFromDeck} onHover={setHoveredCard} emptyMessage="Your Deck is Empty" source="deck" /> <CardsDisplay cards={deck} viewMode={viewMode} cardWidth={cardWidth} onCardClick={removeFromDeck} onHover={setHoveredCard} emptyMessage="Your Library is Empty" source="deck" />
</div> </div>
</DroppableZone> </DroppableZone>
</div> </div>
@@ -613,7 +625,13 @@ export const DeckBuilderView: React.FC<DeckBuilderViewProps> = ({ initialPool, a
const DeckCardItem = ({ card, useArtCrop, isFoil, onCardClick, onHover }: any) => { const DeckCardItem = ({ card, useArtCrop, isFoil, onCardClick, onHover }: any) => {
const displayImage = useArtCrop ? card.imageArtCrop : card.image; const displayImage = useArtCrop ? card.imageArtCrop : card.image;
const { onTouchStart, onTouchEnd, onTouchMove, onClick } = useCardTouch(onHover, () => onCardClick(card), card); const { onTouchStart, onTouchEnd, onTouchMove, onClick } = useCardTouch(onHover, () => {
if (window.matchMedia('(pointer: coarse)').matches) {
onHover(card);
} else {
onCardClick(card);
}
}, card);
return ( return (
<div <div