Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 4x 138x 138x 138x 138x 138x 138x 138x 138x 138x 138x | import React from 'react';
import Animated, {
interpolate,
useAnimatedStyle,
useSharedValue,
withRepeat,
withTiming,
} from 'react-native-reanimated';
import { DimensionValue, StyleProp, View, ViewStyle } from 'react-native';
import { makeStyles } from '@repo/ui/themes/makeStyles';
interface SkeletonProps {
width: DimensionValue;
height: DimensionValue;
radius?: number;
style?: StyleProp<ViewStyle>;
}
export const Skeleton = ({ width, height, radius = 6, style }: SkeletonProps) => {
const styles = useStyles();
const progress = useSharedValue(0);
React.useEffect(() => {
progress.value = withRepeat(withTiming(1, { duration: 1200 }), -1, false);
}, [progress]);
const animatedStyle = useAnimatedStyle(() => {
const translationWidth = typeof width === 'number' ? width : 300;
const translateX = interpolate(progress.value, [0, 1], [-translationWidth, translationWidth]);
return { transform: [{ translateX }] };
});
return (
<View
className="overflow-hidden"
style={[styles.container, { width, height, borderRadius: radius }, style]}
>
<Animated.View className="opacity-50" style={[styles.shimmer, animatedStyle]} />
</View>
);
};
const useStyles = makeStyles(theme => ({
container: {
backgroundColor: theme.colors.skeleton.default,
},
shimmer: {
width: '100%',
height: '100%',
backgroundColor: theme.colors.skeleton.active,
},
}));
|