Skip to content

Commit

Permalink
feat:: Add pagination component to onboarding screen
Browse files Browse the repository at this point in the history
  • Loading branch information
michalfirszt committed Sep 5, 2024
1 parent d66ca73 commit e258073
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
13 changes: 12 additions & 1 deletion examples/common_expo/app/onboarding.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Animated, {
useAnimatedRef,
useAnimatedScrollHandler,
useSharedValue,
} from 'react-native-reanimated';
import { SafeAreaView, StyleSheet, View } from 'react-native';
Expand All @@ -9,6 +10,7 @@ import {
OnboardingListItem,
OnboardingItem,
OnboardingWrapper,
Pagination,
} from '@/components/Onboarding';

const items: OnboardingItem[] = [
Expand All @@ -18,9 +20,16 @@ const items: OnboardingItem[] = [
];

export default function Onboarding() {
const offsetX = useSharedValue(0);
const flatListIndex = useSharedValue(0);
const flatListRef = useAnimatedRef<Animated.FlatList<OnboardingItem>>();

const handleOnScroll = useAnimatedScrollHandler({
onScroll: (event) => {
offsetX.value = event.contentOffset.x;
},
});

return (
<OnboardingWrapper>
<SafeAreaView style={styles.container}>
Expand All @@ -34,12 +43,14 @@ export default function Onboarding() {
onViewableItemsChanged={({ viewableItems }) => {
flatListIndex.value = viewableItems[0].index ?? 0;
}}
onScroll={handleOnScroll}
bounces={false}
showsHorizontalScrollIndicator={false}
horizontal
pagingEnabled
/>
<View style={styles.bottomPanel}>
<Pagination length={items.length} offsetX={offsetX} />
<NextButton
flatListRef={flatListRef}
listIndex={flatListIndex}
Expand All @@ -57,7 +68,7 @@ const styles = StyleSheet.create({
},
bottomPanel: {
flexDirection: 'row',
justifyContent: 'flex-end',
justifyContent: 'space-between',
paddingHorizontal: 24,
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FC } from 'react';
import { StyleSheet, View } from 'react-native';
import { SharedValue } from 'react-native-reanimated';

import { PaginationItem } from './PaginationItem';

type PaginationProps = {
length: number;
offsetX: SharedValue<number>;
};

export const Pagination: FC<PaginationProps> = ({ length, offsetX }) => (
<View style={styles.container}>
{[...Array(length).keys()].map((_, index) => (
<PaginationItem
key={index.toString()}
itemIndex={index}
offsetX={offsetX}
/>
))}
</View>
);

const styles = StyleSheet.create({
container: {
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { FC } from 'react';
import { StyleSheet, useWindowDimensions } from 'react-native';
import Animated, {
Extrapolation,
interpolate,
interpolateColor,
SharedValue,
useAnimatedStyle,
} from 'react-native-reanimated';

type PaginationItemProps = {
itemIndex: number;
offsetX: SharedValue<number>;
};

export const PaginationItem: FC<PaginationItemProps> = ({
itemIndex,
offsetX,
}) => {
const { width: SCREEN_WIDTH } = useWindowDimensions();

const animatedItemStyle = useAnimatedStyle(() => {
const backgroundColor = interpolateColor(
offsetX.value,
[
(itemIndex - 1) * SCREEN_WIDTH,
itemIndex * SCREEN_WIDTH,
(itemIndex + 1) * SCREEN_WIDTH,
],
['#e2e2e2', 'blue', '#e2e2e2'],
);

const width = interpolate(
offsetX.value,
[
(itemIndex - 1) * SCREEN_WIDTH,
itemIndex * SCREEN_WIDTH,
(itemIndex + 1) * SCREEN_WIDTH,
],
[32, 16, 32],
Extrapolation.CLAMP,
);

return {
width,
backgroundColor,
};
});

return <Animated.View style={[styles.item, animatedItemStyle]} />;
};

const styles = StyleSheet.create({
item: {
borderRadius: 5,
height: 10,
marginHorizontal: 4,
width: 32,
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Pagination';
1 change: 1 addition & 0 deletions examples/common_expo/components/Onboarding/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './NextButton';
export * from './OnboardingListItem';
export * from './OnboardingWrapper';
export * from './Pagination';

0 comments on commit e258073

Please sign in to comment.