| 1 | import React from 'react';
|
| 2 | import {
|
| 3 | View,
|
| 4 | StyleSheet,
|
| 5 | Pressable,
|
| 6 | ViewStyle,
|
| 7 | } from 'react-native';
|
| 8 | import { ThemedText } from '@/components/misc/themed-text'
|
| 9 | import { Row, Between } from '@/components/ui/LayoutHelpers';
|
| 10 |
|
| 11 | import { Colors, Typography, Spacing, BorderRadius } from '@/constants/theme';
|
| 12 | import { useThemeColor } from '@/hooks/use-theme-color';
|
| 13 |
|
| 14 | interface SectionProps {
|
| 15 | children: React.ReactNode;
|
| 16 | style?: ViewStyle;
|
| 17 | }
|
| 18 |
|
| 19 | export const Section: React.FC<SectionProps> = ({ children, style }) => {
|
| 20 | const styles = StyleSheet.create({
|
| 21 | section: {
|
| 22 | marginBottom: Spacing.sectionGap,
|
| 23 | },
|
| 24 | });
|
| 25 | return <View style={[styles.section, style]}>{children}</View>;
|
| 26 | };
|
| 27 |
|
| 28 | interface SectionHeaderProps {
|
| 29 | title: string;
|
| 30 | subtitle?: string;
|
| 31 | actionLabel?: string;
|
| 32 | onActionPress?: () => void;
|
| 33 | style?: ViewStyle;
|
| 34 | }
|
| 35 |
|
| 36 | // XXX: A Section must either have a label as a pill/informative thing
|
| 37 | // or it should be a link
|
| 38 | export const SectionHeader: React.FC<SectionHeaderProps> = ({
|
| 39 | title,
|
| 40 | subtitle,
|
| 41 | info,
|
| 42 | actionLabel,
|
| 43 | onActionPress,
|
| 44 | style,
|
| 45 | }) => {
|
| 46 | const textColor = useThemeColor({}, 'text');
|
| 47 | const tintColor = useThemeColor({}, 'tint');
|
| 48 | const textSecondaryColor = useThemeColor({}, 'textSecondary')
|
| 49 |
|
| 50 | const styles = StyleSheet.create({
|
| 51 | headerContainer: {
|
| 52 | marginBottom: (Spacing.cardGap * 2),
|
| 53 | },
|
| 54 | title: {
|
| 55 | fontSize: Typography.headlineMd.fontSize,
|
| 56 | fontWeight: Typography.headlineMd.fontWeight,
|
| 57 | color: textColor,
|
| 58 | },
|
| 59 | subtitle: {
|
| 60 | fontSize: 14,
|
| 61 | color: textSecondaryColor,
|
| 62 | lineHeight: 20,
|
| 63 | marginTop: 4
|
| 64 | },
|
| 65 | actionButton: {
|
| 66 | padding: 4,
|
| 67 | },
|
| 68 | actionText: {
|
| 69 | fontSize: Typography.bodyMd.fontSize,
|
| 70 | fontWeight: '600',
|
| 71 | color: tintColor,
|
| 72 | },
|
| 73 | });
|
| 74 |
|
| 75 | // TODO: Rework these when we finally have chips/badges
|
| 76 | return (
|
| 77 | <View style={[styles.headerContainer, style]}>
|
| 78 | <Between>
|
| 79 | <ThemedText style={styles.title}>
|
| 80 | {title}
|
| 81 | </ThemedText>
|
| 82 |
|
| 83 | {info && !actionLabel && (
|
| 84 | <ThemedText>
|
| 85 | {info}
|
| 86 | </ThemedText>
|
| 87 | )}
|
| 88 |
|
| 89 | {actionLabel && !info && onActionPress && (
|
| 90 | <Pressable
|
| 91 | style={styles.actionButton}
|
| 92 | onPress={onActionPress}
|
| 93 | hitSlop={8}
|
| 94 | >
|
| 95 | <ThemedText style={styles.actionText}>
|
| 96 | {actionLabel}
|
| 97 | </ThemedText>
|
| 98 | </Pressable>
|
| 99 | )}
|
| 100 | </Between>
|
| 101 |
|
| 102 | {subtitle && (
|
| 103 | <Row>
|
| 104 | <ThemedText style={styles.subtitle}>
|
| 105 | {subtitle}
|
| 106 | </ThemedText>
|
| 107 | </Row>
|
| 108 | )}
|
| 109 | </View>
|
| 110 | );
|
| 111 | };
|
| 112 |
|