From 020d71a741295fff193c7320fd1169b47f64e2ef Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 29 Nov 2024 21:17:47 +0000 Subject: [PATCH] Sync scroll to swipe --- src/view/com/home/HomeHeader.tsx | 1 + src/view/com/pager/Pager.tsx | 1 + src/view/com/pager/TabBar.tsx | 102 ++++++++++++++++++++++--------- 3 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/view/com/home/HomeHeader.tsx b/src/view/com/home/HomeHeader.tsx index 31c7135634..a9647f8419 100644 --- a/src/view/com/home/HomeHeader.tsx +++ b/src/view/com/home/HomeHeader.tsx @@ -62,6 +62,7 @@ export function HomeHeader( testID={props.testID} items={items} indicatorColor={pal.colors.link} + dragGesture={props.dragGesture} /> ) diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index c8a4d9487a..0a22806d2e 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -99,6 +99,7 @@ export const Pager = forwardRef>( onPageSelected(e: PagerViewOnPageSelectedEventData) { 'worklet' dragPage.set(e.position) + dragProgress.set(0) runOnJS(onPageSelectedJSThread)(e.position) }, }, diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index 1582bde685..1c5b4e2fa8 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -1,5 +1,12 @@ -import {useCallback, useMemo, useRef} from 'react' +import {useCallback, useMemo} from 'react' import {ScrollView, StyleSheet, View} from 'react-native' +import Animated, { + scrollTo, + useAnimatedReaction, + useAnimatedRef, + useAnimatedStyle, + useSharedValue, +} from 'react-native-reanimated' import {usePalette} from '#/lib/hooks/usePalette' import {PressableWithHover} from '../util/PressableWithHover' @@ -21,9 +28,10 @@ export function TabBar({ indicatorColor, onSelect, onPressSelected, + dragGesture, }: TabBarProps) { const pal = usePalette('default') - const scrollElRef = useRef(null) + const scrollElRef = useAnimatedRef() const indicatorStyle = useMemo( () => ({borderBottomColor: indicatorColor || pal.colors.link}), [indicatorColor, pal], @@ -39,6 +47,30 @@ export function TabBar({ [onSelect, selectedPage, onPressSelected], ) + const contentSize = useSharedValue(0) + const containerSize = useSharedValue(0) + const itemsLength = items.length + const {dragPage, dragProgress} = dragGesture + + useAnimatedReaction( + () => dragPage.get(), + (page, prevPage) => { + if (page !== prevPage) { + const offsetPerPage = contentSize.get() - containerSize.get() + const offset = (dragPage.get() / (itemsLength - 1)) * offsetPerPage + scrollTo(scrollElRef, offset, 0, false) + } + }, + ) + + const contentStyle = useAnimatedStyle(() => { + const offsetPerPage = contentSize.get() - containerSize.get() + const offset = (dragProgress.get() / (itemsLength - 1)) * offsetPerPage + return { + transform: [{translateX: -offset}], + } + }) + return ( - {items.map((item, i) => { - const selected = i === selectedPage - return ( - onPressItem(i)} - accessibilityRole="tab"> - - - {item} - - - - ) - })} + contentContainerStyle={styles.contentContainer} + onLayout={e => { + containerSize.set(e.nativeEvent.layout.width) + }}> + { + contentSize.set(e.nativeEvent.layout.width) + }} + style={[ + contentStyle, + { + flexDirection: 'row', + }, + ]}> + {items.map((item, i) => { + const selected = i === selectedPage + return ( + onPressItem(i)} + accessibilityRole="tab"> + + + {item} + + + + ) + })} +