Swiping! - #116
Conversation
✅ Deploy Preview for redi-love ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
clementroze
left a comment
There was a problem hiding this comment.
Hello! note to my reviewers - lots of this was Claude-generated since im just a lil designer dabbling in frontend, but its the result of me carefully prompting my pet LLM and feeding it enough information for it to achieve the vision i had (trust trust guys)
| const TUTORIAL_CARDS: TutorialCard[] = [ | ||
| { |
There was a problem hiding this comment.
these are the first yellow tutorial cards that a user sees to learn how the system works
it includes the 3 core actions: swiping to dismiss, tapping the card to open the sheet, and opening the filters menu
| useEffect(() => { | ||
| AsyncStorage.getItem(TOUR_STORAGE_KEY).then((val: string | null) => { | ||
| setTourSeen(val === 'true'); | ||
| }); | ||
| }, []); |
There was a problem hiding this comment.
tour should only show once
| <AppText | ||
| variant="bodySmall" | ||
| style={{ color: AppColors.foregroundDimmer }} | ||
| > | ||
| RESET TOUR | ||
| </AppText> |
There was a problem hiding this comment.
Temporary button just for debugging tour
| return ( | ||
| <View | ||
| key={`${matchProfile.netid}-${m.promptId ?? matchIndex}`} | ||
| style={{ | ||
| width: width - 60, | ||
| marginRight: 12, | ||
| }} |
There was a problem hiding this comment.
All this was the old UI which we are revamping
| style={[ | ||
| styles.blob, | ||
| { | ||
| width: 180, |
There was a problem hiding this comment.
in the future we might want to make these decoration dots random position but for this MVP version i think we can just do this for now
| // Architecture: instead of rotating the cards array (which causes cards to | ||
| // jump between DOM slots, producing flashes), we keep cards fixed in the array | ||
| // and track the current "top" index. Each card slot has its own z-index driven | ||
| // by its distance from the top. The top card flies out, and only AFTER it has | ||
| // fully left the screen do we advance the index — with everything already in | ||
| // the correct visual position so no flash is possible. |
There was a problem hiding this comment.
FYI this entire part i admittedly had not much invovlement with as i had mr claude do it (the swiping, stack mechanis, shadowing, animation/morphing into the sheet, etc.)
So i just made sure to prompt Claude into making something that looked like the mocks and that felt nice to use. And i made sure to test it plenty
| const doSubmit = useCallback(() => { | ||
| // 1. Close the sheet immediately (no spring — just hide it). | ||
| expandProgress.setValue(0); | ||
| setIsExpanded(false); | ||
| setCardRect(null); |
| const overlayTop = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [cr.y, SHEET_TOP] }); | ||
| const overlayLeft = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [cr.x, SHEET_MARGIN] }); | ||
| const overlayRight = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [width - cr.x - cr.w, SHEET_MARGIN] }); | ||
| const overlayHeight = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [cr.h, SHEET_HEIGHT] }); | ||
| const backdropOpacity = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [0, 0.5] }); | ||
| const cardContentOpacity = expandProgress.interpolate({ inputRange: [0, 0.3, 0.5], outputRange: [1, 1, 0], extrapolate: 'clamp' }); | ||
| const sheetContentOpacity = expandProgress.interpolate({ inputRange: [0.45, 0.75, 1], outputRange: [0, 0, 1], extrapolate: 'clamp' }); | ||
| const overlayBorderBottomRadius = expandProgress.interpolate({ inputRange: [0, 1], outputRange: [24, 48] }); |
There was a problem hiding this comment.
lol this downward curving slope caused by the syntax highlighting is visually quite nice :)
|
|
||
| return ( | ||
| <View style={styles.skipOuter}> | ||
| <Animated.View style={[styles.skipFill, styles.skipFillLeft, { transform: [{ translateX: leftTranslateX }, { translateY: fillTranslateY }] }]} pointerEvents="none" /> |
There was a problem hiding this comment.
i think one little bug that i've been trying to deal with is that there's a noticeable flash each time you swipe a card to dismiss it for later. it's minor enough to not be catastrophic but i'm still trying to figure out how to fix it 😭
| @@ -0,0 +1,230 @@ | |||
| /** | |||
There was a problem hiding this comment.
all this is TBD test placeholder data, but here's how i imagine it would look like to edit the stack manually. But ofc ideally all the cards are automatically populated.
|
For the match cards, what did we have in mind to complete the action (Say you open the profile and like / dislike it and want to move forward / discard)? I was able to test the functionality with my account but there isn't a way to resolve it. This is what I have rn (Was able to hook it up to the backend) Screen.Recording.2026-04-15.at.6.02.16.PM.mov |
@glopes2023 i think for profiles, there shoudln't be a way to "complete" it? Since match cards are slightly different. Maybe they should always stay in the stack jsut because theyre special. THe "View full profile" functionality you showed in the video looks good though! |
Should we at least re-integrate the nudge functionality we originally had in place? i.e. adding a button to send a nudge to so users can interact with their match |
@glopes2023 yes! that should still be there i think we coud add a 3rd button here that says Nudge it should also appear here (we already have the full profile page built out so we can just use that): |
Summaryfrontend/app/components/ui/CardSheetContent.tsx, frontend/app/components/ui/cardTypes.ts, frontend/app/(auth)/(tabs)/index.tsx, frontend/app/components/ui/UserOptionsSheet.tsx
Test PlanSeeded a test match between gl532 and sona using backend/scripts/seed-test-match.ts See demo below: Notes:I was between having the back button up on the top left or on the bottom with the rest of the interaction buttons in the profile. Please lmk what would be preferred. |
|
thank you @glopes2023 ! Check out the video and interactions look great, just three lil nits:
|
I didn't change anything about that component, and it looks to be the same for all other buttons of its kind in my version of the app. Aside from this, I made all the adjustments requested. |
|
abrar-amin
left a comment
There was a problem hiding this comment.
Overall looks pretty sick! I want to mess around with the animations a bit more, but that can be a new PR. I have tested the feature on my end, and fixed a few things, and it seems to work.
To the moon!
| clearMatchCache, | ||
| getCachedMatchData, | ||
| } from '@/app/utils/matchCache'; | ||
| MOCK_MATCH_CARDS, |
There was a problem hiding this comment.
We shouldn't have mock data in the final app
There was a problem hiding this comment.
yupp these were just for testing
| const [currentMatches, setCurrentMatches] = useState<MatchWithProfile[]>([]); | ||
| // ── TEMPORARY PLACEHOLDER ──────────────────────────────────────────────────── | ||
| // Seeds match cards from existing chat conversations so the card stack isn't | ||
| // empty during development. Remove once the real match pipeline is wired up. |
There was a problem hiding this comment.
This should be removed
| // ── TEMPORARY PLACEHOLDER ─────────────────────────────────────────────── | ||
| // Builds match cards from existing chat conversations for dev/testing. | ||
| // Remove this block once the real weekly-match pipeline populates the feed. | ||
| try { |
There was a problem hiding this comment.
Once again, shouldn't have this here it hink
There was a problem hiding this comment.
i think we keep it for now cuz we're not done, see here for context
| }; | ||
|
|
||
| const [animationTrigger, setAnimationTrigger] = useState(0); | ||
| // Build the daily card list: interleave mock cards with real match cards |
There was a problem hiding this comment.
Why interleave mock and real cards
| <Svg width={size} height={size} viewBox="0 0 24 24" fill="none"> | ||
| {/* House body */} | ||
| <Path | ||
| d="M15 13.0005V21.0005H19C19.5304 21.0005 20.0391 20.7898 20.4142 20.4147C20.7893 20.0396 21 19.5309 21 19.0005V10.0005C21.0001 9.70955 20.9367 9.4221 20.8142 9.1582C20.6918 8.89429 20.5132 8.66028 20.291 8.47248L13.291 2.47248C12.93 2.16739 12.4726 2 12 2C11.5274 2 11.07 2.16739 10.709 2.47248L3.709 8.47248C3.4868 8.66028 3.30824 8.89429 3.18579 9.1582C3.06333 9.4221 2.99993 9.70955 3 10.0005V19.0005C3 19.5309 3.21071 20.0396 3.58579 20.4147C3.96086 20.7898 4.46957 21.0005 5 21.0005H9V13.0005C9 12.7353 9.10536 12.4809 9.29289 12.2934C9.48043 12.1058 9.73478 12.0005 10 12.0005H14C14.2652 12.0005 14.5196 12.1058 14.7071 12.2934C14.8946 12.4809 15 12.7353 15 13.0005Z" |
There was a problem hiding this comment.
this is just the home icon on the navbar
| style={[ | ||
| styles.blob, | ||
| { | ||
| width: 180, |









Changes:
FilledHomeIconcomponent._layout.tsxandindex.tsxfor tab navigation.CardContent,CardSheetContent,CardStack,cardTypes,mockCards).Features
Details
Swiping a card
Screen.Recording.2026-04-08.at.1.45.47.AM.mov
Opening a sheet from the card
Screen.Recording.2026-04-08.at.1.46.02.AM.mov
Done state
Screen.Recording.2026-04-08.at.1.46.23.AM.mov
Tour/tutorial
Screen.Recording.2026-04-08.at.1.46.45.AM.mov
FIlter menu
Screen.Recording.2026-04-08.at.1.48.41.AM.mov