1 version

This commit is contained in:
JUSN committed 2026-07-12 19:59:15 +02:00
1 parent f1165b5404
commit 88c49e1b54
39 files changed
+9328 -52

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
/**
* Dringlichkeits-Ampel als gut sichtbares Banner.
* Farbe + Symbol + Text — nicht nur Farbe (Barrierefreiheit: Farbenblindheit).
*/
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { AmpelStatus } from '../utils/ampel';
import { abstand, schrift } from '../theme';
const SYMBOL: Record<string, string> = { rot: '⚠️', gelb: '⏰', gruen: 'ℹ️' };
export function Ampel({ status }: { status: AmpelStatus }) {
return (
<View
style={[styles.banner, { backgroundColor: status.hintergrund, borderColor: status.farbe }]}
accessibilityRole="alert"
accessibilityLabel={`Dringlichkeit: ${status.text}`}
>
<Text style={styles.symbol}>{SYMBOL[status.stufe]}</Text>
<Text style={[styles.text, { color: status.farbe }]}>{status.text}</Text>
</View>
);
}
const styles = StyleSheet.create({
banner: {
flexDirection: 'row',
alignItems: 'center',
borderWidth: 2,
borderRadius: 12,
padding: abstand.m,
gap: abstand.s,
},
symbol: { fontSize: 28 },
text: { flex: 1, fontSize: schrift.gross, fontWeight: '700' },
});
+76
View File
@@ -0,0 +1,76 @@
/**
* Großer, barrierefreier Button: min. 56px hoch, große Schrift,
* hoher Kontrast. Varianten: primär (gefüllt) und sekundär (Umriss).
*/
import React from 'react';
import { ActivityIndicator, Pressable, StyleSheet, Text } from 'react-native';
import { farben, schrift, abstand, TOUCH_TARGET } from '../theme';
interface Props {
titel: string;
onPress: () => void;
variante?: 'primaer' | 'sekundaer' | 'gefahr';
deaktiviert?: boolean;
laedt?: boolean;
symbol?: string;
}
export function GrossButton({
titel,
onPress,
variante = 'primaer',
deaktiviert = false,
laedt = false,
symbol,
}: Props) {
const istPrimaer = variante === 'primaer';
const istGefahr = variante === 'gefahr';
return (
<Pressable
onPress={onPress}
disabled={deaktiviert || laedt}
accessibilityRole="button"
accessibilityLabel={titel}
style={({ pressed }) => [
styles.button,
istPrimaer && styles.primaer,
variante === 'sekundaer' && styles.sekundaer,
istGefahr && styles.gefahr,
(deaktiviert || laedt) && styles.deaktiviert,
pressed && styles.gedrueckt,
]}
>
{laedt ? (
<ActivityIndicator color={istPrimaer || istGefahr ? farben.primaerText : farben.primaer} />
) : (
<Text
style={[
styles.text,
(istPrimaer || istGefahr) && { color: farben.primaerText },
variante === 'sekundaer' && { color: farben.primaer },
]}
>
{symbol ? `${symbol} ` : ''}
{titel}
</Text>
)}
</Pressable>
);
}
const styles = StyleSheet.create({
button: {
minHeight: TOUCH_TARGET,
borderRadius: 14,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: abstand.l,
paddingVertical: abstand.s,
},
primaer: { backgroundColor: farben.primaer },
sekundaer: { backgroundColor: farben.hintergrund, borderWidth: 2, borderColor: farben.primaer },
gefahr: { backgroundColor: farben.fehler },
deaktiviert: { opacity: 0.5 },
gedrueckt: { opacity: 0.8 },
text: { fontSize: schrift.gross, fontWeight: '700', textAlign: 'center' },
});