summaryrefslogtreecommitdiff
path: root/apps/mobile/components/TaskListSkeleton.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mobile/components/TaskListSkeleton.tsx')
-rw-r--r--apps/mobile/components/TaskListSkeleton.tsx119
1 files changed, 119 insertions, 0 deletions
diff --git a/apps/mobile/components/TaskListSkeleton.tsx b/apps/mobile/components/TaskListSkeleton.tsx
new file mode 100644
index 0000000..60e747d
--- /dev/null
+++ b/apps/mobile/components/TaskListSkeleton.tsx
@@ -0,0 +1,119 @@
+import React, { useEffect, useRef } from 'react';
+import {
+ View,
+ StyleSheet,
+ Animated,
+ useColorScheme,
+} from 'react-native';
+import { Colors } from '../constants/Colors';
+
+interface SkeletonRowProps {
+ delay?: number;
+}
+
+function SkeletonRow({ delay = 0 }: SkeletonRowProps) {
+ const colorScheme = useColorScheme() ?? 'light';
+ const colors = Colors[colorScheme];
+ const opacity = useRef(new Animated.Value(0.3)).current;
+
+ useEffect(() => {
+ const animation = Animated.loop(
+ Animated.sequence([
+ Animated.timing(opacity, {
+ toValue: 0.7,
+ duration: 800,
+ useNativeDriver: true,
+ delay,
+ }),
+ Animated.timing(opacity, {
+ toValue: 0.3,
+ duration: 800,
+ useNativeDriver: true,
+ }),
+ ])
+ );
+ animation.start();
+ return () => animation.stop();
+ }, [opacity, delay]);
+
+ const bgColor = colorScheme === 'dark' ? '#374151' : '#e5e7eb';
+
+ return (
+ <View
+ style={[
+ styles.row,
+ {
+ backgroundColor: colors.card,
+ borderColor: colors.border,
+ },
+ ]}
+ >
+ <Animated.View
+ style={[
+ styles.dot,
+ { backgroundColor: bgColor, opacity },
+ ]}
+ />
+ <View style={styles.content}>
+ <Animated.View
+ style={[
+ styles.titleBar,
+ { backgroundColor: bgColor, opacity },
+ ]}
+ />
+ <Animated.View
+ style={[
+ styles.subtitleBar,
+ { backgroundColor: bgColor, opacity },
+ ]}
+ />
+ </View>
+ </View>
+ );
+}
+
+export function TaskListSkeleton() {
+ return (
+ <View style={styles.container}>
+ <SkeletonRow delay={0} />
+ <SkeletonRow delay={100} />
+ <SkeletonRow delay={200} />
+ <SkeletonRow delay={300} />
+ <SkeletonRow delay={400} />
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ row: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: 16,
+ paddingHorizontal: 16,
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ minHeight: 64,
+ },
+ dot: {
+ width: 10,
+ height: 10,
+ borderRadius: 5,
+ marginRight: 12,
+ },
+ content: {
+ flex: 1,
+ gap: 8,
+ },
+ titleBar: {
+ height: 16,
+ width: '70%',
+ borderRadius: 4,
+ },
+ subtitleBar: {
+ height: 12,
+ width: '40%',
+ borderRadius: 4,
+ },
+});