Skip to content

Instantly share code, notes, and snippets.

@lindesvard
Last active April 25, 2024 00:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lindesvard/11680f743166d67e2924a8cc45281e0a to your computer and use it in GitHub Desktop.
Save lindesvard/11680f743166d67e2924a8cc45281e0a to your computer and use it in GitHub Desktop.
import React, { createContext } from 'react';
import { useWindowDimensions, View } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withSpring,
} from 'react-native-reanimated';
import { LinearGradient } from 'expo-linear-gradient';
import { Stack } from 'expo-router';
import { COLORS } from '@/constants';
const OnboardingContext = createContext<{
next: () => void;
prev: () => void;
}>({
next: () => {
//
},
prev: () => {
//
},
});
export function useOnboarding() {
return React.useContext(OnboardingContext);
}
export function OnboardingRoot({ children }: { children: React.ReactNode }) {
const MAX_STEPS = React.Children.count(children);
const step = useSharedValue(0);
const dimensions = useWindowDimensions();
const handlePrev = () => {
if (step.value > 0) {
step.value -= 1;
}
};
const handleNext = () => {
if (step.value < MAX_STEPS - 1) {
step.value += 1;
}
};
const animatedStyle = useAnimatedStyle(() => {
return {
flex: 1,
flexGrow: 1,
transform: [
{
translateY: withSpring(step.value * dimensions.height * -1, {
damping: 20,
stiffness: 90,
}),
},
],
};
});
const animatedProgress = useAnimatedStyle(() => {
const width = withSpring(step.value / MAX_STEPS, {
damping: 20,
stiffness: 90,
});
return {
backgroundColor: COLORS.primary,
flex: width,
};
});
return (
<View className="flex-1">
<Stack.Screen options={{ headerShown: false }} />
<OnboardingContext.Provider
value={{ next: handleNext, prev: handlePrev }}
>
<Animated.View style={animatedStyle}>
{React.Children.map(children, (child, index) => {
return (
<View
key={index}
style={{
width: dimensions.width,
height: dimensions.height,
}}
>
{child}
</View>
);
})}
</Animated.View>
</OnboardingContext.Provider>
<LinearGradient
colors={[
'rgba(255,255,255,1)',
'rgba(255,255,255,0.8)',
'rgba(255,255,255,0)',
]}
style={{
width: dimensions.width,
height: 200,
position: 'absolute',
top: 0,
left: 0,
}}
/>
<View className="absolute left-6 right-6 top-20">
<View className="h-[10px] w-full flex-row overflow-hidden rounded-full bg-[#C9D7DE]">
<Animated.View style={animatedProgress} />
</View>
</View>
{/* <View className="absolute bottom-20 left-0 right-0 flex-row">
<Button onPress={() => handlePrev()}>Prev</Button>
<Button onPress={() => handleNext()}>{mounted}</Button>
</View> */}
</View>
);
}
import { OnboardingRoot } from '@/components/onboarding/onboarding';
import Congratulations from '@/components/onboarding/screens/1-congratulations';
import SearchDevice from '@/components/onboarding/screens/10-search-device';
import ConfirmDevice from '@/components/onboarding/screens/15-confirm-device';
import ConnectDevice from '@/components/onboarding/screens/5-connect-device';
export default function Register() {
return (
<OnboardingRoot>
<Congratulations />
<ConnectDevice />
<SearchDevice />
<ConfirmDevice />
</OnboardingRoot>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment