Conversation
…ction buttons Implements a full Tinder-style UI using Symbols framework: - ProfileCard: displays user photo, name, age, job, school, distance with gradient overlay and LIKE/NOPE/SUPER LIKE stamps - SwipeCard: handles pointer drag gestures with rotation, threshold-based swipe detection, and animated card dismissal - TinderStack: manages card stack state, profile cycling, action handling (like/nope/superlike/rewind), and empty state - ActionButtons: rewind, nope, super like, like, and boost buttons with themed colors - TinderHeader: app header with logo and navigation icons - Mock profile data with 6 sample profiles in snippets - Swipe animations (swipeLeft, swipeRight, swipeUp, cardStackIn, pulseGlow) in design system - Tinder color palette (tinderPink, tinderGold, tinderBlue, tinderGreen, tinderRed, tinderPurple) - New icons: heart, heartOutline, tinderClose, star, rewind, bolt, mapPin, briefcase, graduationCap, info https://claude.ai/code/session_019CMCq1QWDzmJbrtf6hoRUp
There was a problem hiding this comment.
Pull request overview
This PR implements a complete Tinder-like card swiping interface as a demonstration UI component. It introduces an interactive dating app experience with gesture-based card swiping, visual feedback stamps, and action buttons, built using the existing component framework.
Changes:
- Added 6 new components (ProfileCard, SwipeCard, TinderStack, TinderHeader, ActionButtons, ActionButton) with swipe gesture handling and state management
- Extended design system with Tinder brand colors, swipe animations, and Tinder-specific icons
- Created
/tinderpage route with sample profile data demonstrating the feature
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| smbls/snippets/profilesData.js | Sample data with 6 user profiles including names, photos, bios, and metadata |
| smbls/snippets/index.js | Export added for profilesData |
| smbls/pages/tinder.js | New page definition combining TinderHeader and TinderStack components |
| smbls/pages/index.js | Route registration for /tinder page |
| smbls/designSystem/icons.js | Added 10 new icons for Tinder UI (heart, star, rewind, bolt, briefcase, etc.) |
| smbls/designSystem/color.js | Added 6 Tinder brand colors (pink, gold, blue, green, red, purple) |
| smbls/designSystem/animation.js | Added 5 swipe-related CSS animations (swipeRight, swipeLeft, swipeUp, cardStackIn, pulseGlow) |
| smbls/components/index.js | Component exports for 6 new components |
| smbls/components/TinderStack.js | Main container managing card deck state, action handling, and user interaction tracking |
| smbls/components/TinderHeader.js | Top navigation bar with profile button, branded logo, and menu button |
| smbls/components/SwipeCard.js | Interactive wrapper with pointer event handlers for drag-based swipe gestures |
| smbls/components/ProfileCard.js | Display component showing user info with photo, gradient overlay, and animated stamps |
| smbls/components/ActionButtons.js | Control panel with 5 action buttons (rewind, nope, super like, like, boost) |
| smbls/components/ActionButton.js | Reusable circular button base with hover and active state animations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| s.apply(function (st) { st.noped.push(profile) }) | ||
| } else if (action === 'superlike') { | ||
| s.apply(function (st) { st.superliked.push(profile) }) | ||
| } else if (action === 'rewind' && s.currentIndex > 0) { |
There was a problem hiding this comment.
The rewind action decrements the currentIndex but does not remove the profile from the liked, noped, or superliked arrays. This creates an inconsistency where a rewound profile remains in the action history arrays even though the user will see it again. The rewind logic should identify which array contains the profile at currentIndex (if any) and remove it before decrementing the index.
| } else if (action === 'rewind' && s.currentIndex > 0) { | |
| } else if (action === 'rewind' && s.currentIndex > 0) { | |
| s.apply(function (st) { | |
| var idx = st.liked.indexOf(profile) | |
| if (idx !== -1) { | |
| st.liked.splice(idx, 1) | |
| } | |
| idx = st.noped.indexOf(profile) | |
| if (idx !== -1) { | |
| st.noped.splice(idx, 1) | |
| } | |
| idx = st.superliked.indexOf(profile) | |
| if (idx !== -1) { | |
| st.superliked.splice(idx, 1) | |
| } | |
| }) |
| interests: profiles[idx].interests, | ||
| swiped: null, | ||
| action: null |
There was a problem hiding this comment.
The SwipeCard component has its own local state (lines 121-132) that includes a swiped property. When SwipeCard's animateOut function calls s.update({ swiped: direction }), it updates its own local state, not the parent TinderStack's state. This means the swipe gesture won't trigger TinderStack's onStateUpdate handler at line 45, so handleAction won't be called and the profile won't be added to the liked/noped/superliked arrays. The swiped state should be managed in TinderStack's state, and SwipeCard should update the parent state using s.parent.update() or a callback prop.
| interests: profiles[idx].interests, | |
| swiped: null, | |
| action: null | |
| interests: profiles[idx].interests |
| setTimeout(function () { | ||
| s.update({ swiped: direction }) | ||
| }, 500) |
There was a problem hiding this comment.
The setTimeout callback in animateOut is not being cleaned up when the component unmounts. If the component is destroyed before the 500ms timeout completes, the state update will attempt to run on an unmounted component. Store the timeout ID in el.scope and clear it in the onRender cleanup function to prevent memory leaks and potential errors.
Summary
This PR introduces a complete Tinder-like card swiping interface with interactive gesture support, profile cards, and action buttons. The implementation includes drag-to-swipe functionality with visual feedback stamps, a card stack system, and a full page layout.
Key Changes
ProfileCard Component: New card component displaying user profile information (name, age, job, school, distance) with a background photo and gradient overlay. Includes animated "LIKE", "NOPE", and "SUPER LIKE" stamps that appear during interactions.
SwipeCard Component: Interactive wrapper component that handles pointer events for drag-based swiping. Implements:
TinderStack Component: State management container that:
ActionButtons Component: Control panel with five action buttons:
TinderHeader Component: Top navigation bar with profile access, branded logo with gradient text, and menu button
ActionButton Base Component: Reusable button component with hover/active states and scale animations
Sample Data: Added
profilesDatasnippet with 6 sample user profiles including images, bios, interests, and metadataDesign System Updates:
Page Integration: New
tinderpage combining header and stack components with proper layout and themingImplementation Details
The swipe detection uses pointer events with clientX/clientY tracking to calculate drag distance and direction. Rotation is applied proportionally to horizontal movement (capped at ±15°). Stamp opacity is calculated based on drag distance thresholds, with different logic for horizontal vs vertical swipes. The component uses CSS transforms for smooth 60fps animations and includes proper cleanup of event listeners on unmount.
https://claude.ai/code/session_019CMCq1QWDzmJbrtf6hoRUp