ueberpruefen
This commit is contained in:
150
src/components/Button.tsx
Normal file
150
src/components/Button.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
TouchableOpacity,
|
||||
Text,
|
||||
StyleSheet,
|
||||
ActivityIndicator,
|
||||
ViewStyle,
|
||||
TextStyle,
|
||||
AccessibilityRole,
|
||||
} from 'react-native';
|
||||
import { colors, spacing, typography, borderRadius, MIN_TAP_SIZE } from '../lib/theme';
|
||||
|
||||
interface ButtonProps {
|
||||
title: string;
|
||||
onPress: () => void;
|
||||
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
disabled?: boolean;
|
||||
loading?: boolean;
|
||||
style?: ViewStyle;
|
||||
textStyle?: TextStyle;
|
||||
accessibilityLabel?: string;
|
||||
accessibilityHint?: string;
|
||||
}
|
||||
|
||||
export const Button: React.FC<ButtonProps> = ({
|
||||
title,
|
||||
onPress,
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
disabled = false,
|
||||
loading = false,
|
||||
style,
|
||||
textStyle,
|
||||
accessibilityLabel,
|
||||
accessibilityHint,
|
||||
}) => {
|
||||
const isDisabled = disabled || loading;
|
||||
|
||||
const buttonStyle = [
|
||||
styles.base,
|
||||
styles[variant],
|
||||
styles[`size_${size}`],
|
||||
isDisabled && styles.disabled,
|
||||
style,
|
||||
];
|
||||
|
||||
const textStyles = [
|
||||
styles.text,
|
||||
styles[`text_${variant}`],
|
||||
styles[`textSize_${size}`],
|
||||
isDisabled && styles.textDisabled,
|
||||
textStyle,
|
||||
];
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={buttonStyle}
|
||||
onPress={onPress}
|
||||
disabled={isDisabled}
|
||||
activeOpacity={0.7}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={accessibilityLabel || title}
|
||||
accessibilityHint={accessibilityHint}
|
||||
accessibilityState={{ disabled: isDisabled }}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator
|
||||
color={variant === 'primary' ? colors.background : colors.primary}
|
||||
size="small"
|
||||
/>
|
||||
) : (
|
||||
<Text style={textStyles}>{title}</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: borderRadius.md,
|
||||
minHeight: MIN_TAP_SIZE,
|
||||
borderWidth: 2, // Retro thick borders
|
||||
},
|
||||
primary: {
|
||||
backgroundColor: colors.primary,
|
||||
borderColor: colors.primaryDark,
|
||||
},
|
||||
secondary: {
|
||||
backgroundColor: colors.backgroundSecondary,
|
||||
borderColor: colors.border,
|
||||
},
|
||||
outline: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 2,
|
||||
borderColor: colors.primary,
|
||||
},
|
||||
ghost: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
size_sm: {
|
||||
paddingHorizontal: spacing.md,
|
||||
paddingVertical: spacing.sm,
|
||||
minHeight: 36,
|
||||
},
|
||||
size_md: {
|
||||
paddingHorizontal: spacing.lg,
|
||||
paddingVertical: spacing.md,
|
||||
},
|
||||
size_lg: {
|
||||
paddingHorizontal: spacing.xl,
|
||||
paddingVertical: spacing.lg,
|
||||
},
|
||||
text: {
|
||||
fontWeight: typography.fontWeight.bold,
|
||||
letterSpacing: 0.5, // Retro spacing
|
||||
textTransform: 'uppercase', // Retro all-caps buttons
|
||||
},
|
||||
text_primary: {
|
||||
color: colors.background,
|
||||
},
|
||||
text_secondary: {
|
||||
color: colors.text,
|
||||
},
|
||||
text_outline: {
|
||||
color: colors.primary,
|
||||
},
|
||||
text_ghost: {
|
||||
color: colors.primary,
|
||||
},
|
||||
textDisabled: {
|
||||
opacity: 0.7,
|
||||
},
|
||||
textSize_sm: {
|
||||
fontSize: typography.fontSize.sm,
|
||||
},
|
||||
textSize_md: {
|
||||
fontSize: typography.fontSize.md,
|
||||
},
|
||||
textSize_lg: {
|
||||
fontSize: typography.fontSize.lg,
|
||||
},
|
||||
});
|
||||
27
src/components/Card.tsx
Normal file
27
src/components/Card.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import { colors, spacing, borderRadius, shadows } from '../lib/theme';
|
||||
|
||||
interface CardProps {
|
||||
children: React.ReactNode;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
elevated?: boolean;
|
||||
}
|
||||
|
||||
export const Card: React.FC<CardProps> = ({ children, style, elevated = true }) => {
|
||||
return (
|
||||
<View style={[styles.card, elevated && shadows.md, style]}>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card: {
|
||||
backgroundColor: colors.card,
|
||||
borderRadius: borderRadius.lg,
|
||||
padding: spacing.lg, // More padding for retro feel
|
||||
borderWidth: 2, // Thicker border for vintage look
|
||||
borderColor: colors.border,
|
||||
},
|
||||
});
|
||||
77
src/components/Input.tsx
Normal file
77
src/components/Input.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
TextInput,
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TextInputProps,
|
||||
ViewStyle,
|
||||
} from 'react-native';
|
||||
import { colors, spacing, typography, borderRadius, MIN_TAP_SIZE } from '../lib/theme';
|
||||
|
||||
interface InputProps extends TextInputProps {
|
||||
label?: string;
|
||||
error?: string;
|
||||
containerStyle?: ViewStyle;
|
||||
}
|
||||
|
||||
export const Input: React.FC<InputProps> = ({
|
||||
label,
|
||||
error,
|
||||
containerStyle,
|
||||
style,
|
||||
...textInputProps
|
||||
}) => {
|
||||
return (
|
||||
<View style={[styles.container, containerStyle]}>
|
||||
{label && (
|
||||
<Text style={styles.label} accessibilityLabel={label}>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
<TextInput
|
||||
style={[styles.input, error && styles.inputError, style]}
|
||||
placeholderTextColor={colors.textTertiary}
|
||||
accessibilityLabel={label || textInputProps.placeholder}
|
||||
{...textInputProps}
|
||||
/>
|
||||
{error && (
|
||||
<Text style={styles.error} accessibilityLiveRegion="polite">
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginBottom: spacing.md,
|
||||
},
|
||||
label: {
|
||||
fontSize: typography.fontSize.sm,
|
||||
fontWeight: typography.fontWeight.bold,
|
||||
color: colors.text,
|
||||
marginBottom: spacing.sm,
|
||||
letterSpacing: 0.5,
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
input: {
|
||||
backgroundColor: colors.background,
|
||||
borderWidth: 2, // Thicker retro border
|
||||
borderColor: colors.border,
|
||||
borderRadius: borderRadius.md,
|
||||
padding: spacing.md,
|
||||
fontSize: typography.fontSize.md,
|
||||
color: colors.text,
|
||||
minHeight: MIN_TAP_SIZE,
|
||||
},
|
||||
inputError: {
|
||||
borderColor: colors.error,
|
||||
},
|
||||
error: {
|
||||
fontSize: typography.fontSize.xs,
|
||||
color: colors.error,
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
});
|
||||
3
src/components/index.ts
Normal file
3
src/components/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './Button';
|
||||
export * from './Card';
|
||||
export * from './Input';
|
||||
Reference in New Issue
Block a user