### Development Setup Commands (Bash) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt Provides essential shell commands for managing project dependencies, running the development server, building for production, executing tests, and linting code. Supports both yarn and npm package managers. ```bash # Install dependencies yarn install # or npm install # Run development server yarn dev # or npm run dev # Server starts at http://localhost:3000 # Build for production yarn build # or npm run build # Run production server yarn start # or npm start # Run Playwright e2e tests yarn test # or npm test # Lint code yarn lint # or npm run lint ``` -------------------------------- ### Playwright E2E Tests for Swipe Gestures (TypeScript) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt Automates swipe gestures using Playwright to test card interactions, counter updates, and undo functionality. It simulates 'like', 'nope', and 'superlike' actions and verifies UI state changes. Requires Playwright and a running application. ```typescript import { test, expect, Page } from "@playwright/test"; import type { SwipeType } from "types"; const elements = { activeCard: 'div[data-testid="active-card"]', likeCount: 'div[data-testid="like-count"]', nopeCount: 'div[data-testid="nope-count"]', superlikeCount: 'div[data-testid="superlike-count"]', undoBtn: 'button[data-testid="undo-btn"]', }; const swipeCard = async ( page: Page, swipeType: SwipeType, point: { x: number; y: number } ) => { const { x, y } = point; await page.mouse.move(x, y); await page.mouse.click(x, y); await page.mouse.down(); if (swipeType === "superlike") { await page.mouse.move(x, y - 2000); } else { await page.mouse.move(x + (swipeType === "like" ? +1000 : -1000), y); } await page.mouse.up(); }; test("should swipe and change count", async ({ page }) => { await page.goto("http://localhost:3000/"); // Get card center position const bb = await page.locator(elements.activeCard).boundingBox(); if (!bb) return; const center = { x: bb.x + bb.width / 2, y: bb.y + bb.height / 2 }; // Test swipe interactions await swipeCard(page, "nope", center); await expect(page.locator(elements.nopeCount)).toHaveText("1"); await swipeCard(page, "like", center); await expect(page.locator(elements.likeCount)).toHaveText("1"); await swipeCard(page, "superlike", center); await expect(page.locator(elements.superlikeCount)).toHaveText("1"); }); test("should undo swipe and update count", async ({ page }) => { await page.goto("http://localhost:3000/"); const bb = await page.locator(elements.activeCard).boundingBox(); if (!bb) return; const center = { x: bb.x + bb.width / 2, y: bb.y + bb.height / 2 }; await swipeCard(page, "like", center); await expect(page.locator(elements.likeCount)).toHaveText("1"); // Undo action await page.locator(elements.undoBtn).click(); await expect(page.locator(elements.likeCount)).toHaveText("0"); }); ``` -------------------------------- ### Next.js API Route for Basic Data Response (TypeScript) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt A simple Next.js API route '/api/hello' that returns a JSON object with a 'name' property. It demonstrates type safety for request and response using NextApiRequest and NextApiResponse. Can be called via fetch or curl. ```typescript // pages/api/hello.ts import type { NextApiRequest, NextApiResponse } from 'next' type Data = { name: string } export default function handler( req: NextApiRequest, res: NextApiResponse ) { res.status(200).json({ name: 'John Doe' }) } // Usage with fetch async function fetchHello() { const response = await fetch('/api/hello'); const data = await response.json(); console.log(data); // { name: 'John Doe' } return data; } // Usage with curl // curl http://localhost:3000/api/hello // Response: {"name":"John Doe"} ``` -------------------------------- ### Card Stack Management and Undo Functionality (TypeScript/React) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt The main page component manages the card stack, swipe results, and undo functionality. It maintains state for cards, results (like, nope, superlike), and a history stack. Input includes card data and swipe actions, with output being the updated UI and state. Dependencies include React's useState and Framer Motion's AnimatePresence. ```tsx import { useState } from "react"; import { AnimatePresence } from "framer-motion"; import CARDS from "@data/cards"; import Card from "@components/Card"; import { CardType, HistoryType, ResultType, SwipeType } from "types"; function Home() { const [cards, setCards] = useState(CARDS); const [result, setResult] = useState({ like: 0, nope: 0, superlike: 0, }); const [history, setHistory] = useState([]); const activeIndex = cards.length - 1; const removeCard = (oldCard: CardType, swipe: SwipeType) => { // Add to history for undo functionality setHistory((current) => [...current, { ...oldCard, swipe }]); // Remove card from stack setCards((current) => current.filter((card) => card.id !== oldCard.id)); // Update result counter setResult((current) => ({ ...current, [swipe]: current[swipe] + 1 })); }; const undoSwipe = () => { const newCard = history.pop(); if (newCard) { const { swipe } = newCard; setHistory((current) => current.filter((card) => card.id !== newCard.id)); setResult((current) => ({ ...current, [swipe]: current[swipe] - 1 })); setCards((current) => [...current, newCard]); } }; return (
{cards.map((card, index) => ( ))}
); } ``` -------------------------------- ### Type Definitions for Type Safety (TypeScript) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt Provides comprehensive TypeScript type definitions to ensure type safety across the application. Includes types for cards, swipe actions, result tracking, and component props. These enhance code reliability and maintainability. ```typescript // types/index.d.ts import CARDS from "data/cards"; type ArrayElementType = ArrType extends readonly (infer ElementType)[] ? ElementType : never; export type CardType = ArrayElementType; // Resulting type: { id: number; emoji: string; name: string; color: string; } export type SwipeType = "like" | "nope" | "superlike"; export type ResultType = { [k in SwipeType]: number }; // Resulting type: { like: number; nope: number; superlike: number; } export type HistoryType = CardType & { swipe: SwipeType }; // Card with additional swipe property for history tracking export interface CardProps { card: CardType; active: boolean; removeCard: (oldCard: CardType, swipe: SwipeType) => void; } // Usage example const exampleResult: ResultType = { like: 10, nope: 5, superlike: 3 }; const exampleHistory: HistoryType = { id: 1, emoji: "🍊", name: "Tangerine", color: "#F36000", swipe: "like" }; ``` -------------------------------- ### Counter Component - Display Swipe Statistics (React/TypeScript) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt A reusable React component that displays numerical statistics for swipe actions (likes, nopes, superlikes). It uses TypeScript for props and includes test identifiers for end-to-end testing. The component expects a label, count, and a testid as props. ```tsx import Counter from "@components/Counter"; import { useState } from "react"; function SwipeCounters() { const [result, setResult] = useState({ like: 5, nope: 3, superlike: 2 }); return (
); } // Counter component implementation interface CounterProps { testid: string; label: string; count: number; } const Counter: React.FC = ({ count, label, testid }) => { return (
{count}
{label}
); }; ``` -------------------------------- ### Draggable Card Component with Swipe Gestures (TypeScript/React) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt The Card component enables animated, draggable cards with swipe gestures (left, right, up). It utilizes Framer Motion for animations and gesture handling. Input is a CardType object, and output is a console log and card removal. Dependencies include Framer Motion's AnimatePresence. ```tsx import { AnimatePresence } from "framer-motion"; import Card from "@components/Card"; import { CardType } from "types"; const SAMPLE_CARD: CardType = { id: 1, emoji: "🍊", name: "Tangerine", color: "#F36000" }; function CardExample() { const [cards, setCards] = useState([SAMPLE_CARD]); const activeIndex = cards.length - 1; const removeCard = (oldCard: CardType, swipe: "like" | "nope" | "superlike") => { console.log(`Card ${oldCard.name} was swiped: ${swipe}`); setCards((current) => current.filter((card) => card.id !== oldCard.id)); }; return (
{cards.map((card, index) => ( ))}
); } ``` -------------------------------- ### Framer Motion Drag Handler for Swipe Detection (TypeScript/React) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt Handles drag gestures using Framer Motion's onDragEnd to detect swipe direction (like, nope, superlike) based on offset thresholds. It updates state to trigger animations and logs detected actions. Requires Framer Motion and React. ```tsx import { PanInfo, motion } from "framer-motion"; import { useState } from "react"; import { CardType } from "types"; function DragHandler() { const [leaveX, setLeaveX] = useState(0); const [leaveY, setLeaveY] = useState(0); const onDragEnd = (_e: any, info: PanInfo) => { // Check vertical swipe (superlike) - threshold: -100px if (info.offset.y < -100) { setLeaveY(-2000); console.log("Superlike detected!"); return; } // Check horizontal swipes - threshold: 100px if (info.offset.x > 100) { setLeaveX(1000); console.log("Like detected!"); } if (info.offset.x < -100) { setLeaveX(-1000); console.log("Nope detected!"); } }; return ( 🍊 ); } ``` -------------------------------- ### Card Data Structure Definition (TypeScript) Source: https://context7.com/deep-codes/framer-tinder-cards/llms.txt Defines the structure for card objects used in the swiping interface. Each card has a unique ID, an emoji representation, a name, and a color theme. This is implemented as a constant array of objects. ```typescript // data/cards.ts const CARDS = [ { id: 0, emoji: "🍅", name: "Tomato", color: "#E42100" }, { id: 1, emoji: "🍊", name: "Tangerine", color: "#F36000" }, { id: 2, emoji: "🍋", name: "Lemon", color: "#F3BC00" }, { id: 3, emoji: "🍐", name: "Pear", color: "#A0A226" }, { id: 4, emoji: "🥬", name: "Lettuce", color: "#349B19" }, { id: 5, emoji: "🫐", name: "Blueberries", color: "#70BBFF" }, { id: 6, emoji: "🍆", name: "Eggplant", color: "#7F4877" }, { id: 7, emoji: "🍇", name: "Grapes", color: "#BC2A6E" }, ]; export default CARDS; // Custom card data example const customCards = [ { id: 0, emoji: "🎮", name: "Gaming", color: "#FF6B6B" }, { id: 1, emoji: "🎨", name: "Art", color: "#4ECDC4" }, { id: 2, emoji: "🎵", name: "Music", color: "#FFE66D" } ]; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.