eletrotupi / tcc/ frontend/components/auth/AuthScreen.tsx6bdc28a3adcc45cf37288df8777dfa536ce0f07a
2.5 KB | 105 lines Raw
1
import React from 'react';
2
import {
3
  KeyboardAvoidingView,
4
  ScrollView,
5
  StyleSheet,
6
  View,
7
  type StyleProp,
8
  type ViewStyle,
9
} from 'react-native';
10
import { SafeAreaView } from 'react-native-safe-area-context';
11
import { Text } from '@/components/ui/Text';
12
import { useThemeColor } from '@/hooks/use-theme-color';
13

14
interface AuthScreenProps {
15
  title?: string;
16
  subtitle?: string;
17
  titleTestID?: string;
18
  // Sits above the title — login puts its animated logo here.
19
  header?: React.ReactNode;
20
  footer?: React.ReactNode;
21
  children?: React.ReactNode;
22
  contentContainerStyle?: StyleProp<ViewStyle>;
23
}
24

25
// The one layout every auth screen shares. Top-aligned on purpose: a form whose
26
// error rows grow must not re-center (and scroll) the whole screen when it does.
27
export function AuthScreen({
28
  title,
29
  subtitle,
30
  titleTestID,
31
  header,
32
  footer,
33
  children,
34
  contentContainerStyle,
35
}: AuthScreenProps) {
36
  const textColor = useThemeColor({}, 'text');
37
  const backgroundColor = useThemeColor({}, 'background');
38

39
  return (
40
    <SafeAreaView style={[styles.container, { backgroundColor }]}>
41
      <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
42
        <ScrollView
43
          contentContainerStyle={[styles.scrollContainer, contentContainerStyle]}
44
          showsVerticalScrollIndicator={false}
45
          keyboardShouldPersistTaps="handled"
46
        >
47
          {header}
48

49
          {(title || subtitle) && (
50
            <View style={styles.header}>
51
              {title && (
52
                <Text testID={titleTestID} style={[styles.title, { color: textColor }]}>
53
                  {title}
54
                </Text>
55
              )}
56
              {subtitle && (
57
                <Text style={[styles.subtitle, { color: textColor, opacity: 0.7 }]}>
58
                  {subtitle}
59
                </Text>
60
              )}
61
            </View>
62
          )}
63

64
          {children}
65

66
          {footer && <View style={styles.footer}>{footer}</View>}
67
        </ScrollView>
68
      </KeyboardAvoidingView>
69
    </SafeAreaView>
70
  );
71
}
72

73
const styles = StyleSheet.create({
74
  container: {
75
    flex: 1,
76
  },
77
  keyboardView: {
78
    flex: 1,
79
  },
80
  scrollContainer: {
81
    flexGrow: 1,
82
    paddingHorizontal: 24,
83
    paddingTop: 24,
84
    paddingBottom: 24,
85
  },
86
  header: {
87
    alignItems: 'center',
88
    marginBottom: 40,
89
  },
90
  title: {
91
    fontSize: 28,
92
    fontWeight: 'bold',
93
    marginBottom: 8,
94
    textAlign: 'center',
95
  },
96
  subtitle: {
97
    fontSize: 16,
98
    textAlign: 'center',
99
    lineHeight: 24,
100
  },
101
  footer: {
102
    marginTop: 'auto',
103
    paddingTop: 24,
104
  },
105
});