feat: rename Deck to Library and implement tap-to-preview for cards in Deck Builder on touch devices.
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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).
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user