From 9088c313cc4873c3704afce2e0384c0c3c4d5ead Mon Sep 17 00:00:00 2001 From: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> Date: Wed, 7 Oct 2026 02:18:40 -0400 Subject: [PATCH] Swipe gesture on the Discover deck (#107) Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com> --- web/src/discover/DeckCard.tsx | 19 +- web/src/discover/DiscoverPage.module.css | 6 + web/src/discover/DiscoverPage.test.tsx | 497 +++++++++++++++++++++++ web/src/discover/DiscoverPage.tsx | 129 +++++- web/src/discover/motion.test.ts | 51 ++- web/src/discover/motion.ts | 42 +- 6 files changed, 720 insertions(+), 24 deletions(-) diff --git a/web/src/discover/DeckCard.tsx b/web/src/discover/DeckCard.tsx index 6c2cb2d..9c4f119 100644 --- a/web/src/discover/DeckCard.tsx +++ b/web/src/discover/DeckCard.tsx @@ -1,3 +1,4 @@ +import type { DOMAttributes } from 'react' import { DIFFICULTIES, type Difficulty } from '../dinners/api.ts' import { Photo } from '../ui/Photo.tsx' import type { SideQuest } from './api.ts' @@ -8,25 +9,35 @@ export const DECK_DEPTH = [0, 1, 2] as const const DIFFICULTY_LABEL: Record = { easy: 'Easy', medium: 'Medium', hard: 'Hard' } +// SwipeHandlers are the pointer handlers that drag the top card. +export type SwipeHandlers = Pick< + DOMAttributes, + 'onPointerDown' | 'onPointerMove' | 'onPointerUp' | 'onPointerCancel' | 'onLostPointerCapture' +> + export type DeckCardProps = { quest: SideQuest // 0 is the top card; 1 and 2 stack behind it. depth: number + // swipe makes the card draggable; only the top card gets it. + swipe?: SwipeHandlers } // DeckCard is one Side quest in the deck. Only the top card is read out and // reachable; the cards behind it are the stack's edge, kept rendered so they // can be promoted. Its "Try it!" and "Pass" stamps stay hidden until a -// decision shows them, and its shade until Pass folds it (see motion.ts). -export function DeckCard({ quest, depth }: DeckCardProps) { +// decision or a drag shows them, and its shade until Pass folds it (see +// motion.ts). +export function DeckCard({ quest, depth, swipe }: DeckCardProps) { const top = depth === 0 const titleId = `side-quest-${quest.id}` return (
@@ -41,7 +52,7 @@ export function DeckCard({ quest, depth }: DeckCardProps) { -