generated from knso/webklar-preview-template
Apple-natives Design: SF Symbols statt Emojis, iOS-System-Optik
- Neue Ikone-Komponente (expo-symbols): echte SF Symbols auf iOS, Material Symbols auf Android — alle Emojis in Buttons/Kacheln/ Checkboxen/Ampel/Chevrons ersetzt - Theme: iOS-Systemgrau (#F2F2F7) statt Papier-Ton, weiße Karten ohne Rahmen und Schatten (wie Einstellungen/Health), "graue Taste" für Sekundär-Buttons statt Umrandung - Kernaussage-Karte: dezenter Marken-Tint statt Textmarker-Gelb - Frist/Termin-Zeilen ohne Emoji-Präfixe - Layout unverändert (Kacheln, Ampel-Streifen, großer Titel) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a670cc1758
commit
4ce397026c
12 files changed
+209
-130
No files matched your search
@@ -23,7 +23,8 @@ import { formatiereDatum } from '../services/erinnerungen';
|
||||
import { berechneAmpel } from '../utils/ampel';
|
||||
import { Ampel } from '../components/Ampel';
|
||||
import { GrossButton } from '../components/GrossButton';
|
||||
import { farben, schrift, abstand, kartenSchatten, TOUCH_TARGET } from '../theme';
|
||||
import { Ikone } from '../components/Ikone';
|
||||
import { farben, schrift, abstand, TOUCH_TARGET } from '../theme';
|
||||
|
||||
type Props = NativeStackScreenProps<RootStackParamList, 'Analyse'>;
|
||||
|
||||
@@ -133,9 +134,13 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={`Sprache ändern. Aktuell: ${sprache.name}`}
|
||||
>
|
||||
<Text style={styles.sprachButtonText}>
|
||||
🌐 {sprache.eigenname} {uebersetzt ? ' (übersetzt…)' : ''}
|
||||
</Text>
|
||||
<View style={styles.sprachZeileInhalt}>
|
||||
<Ikone name="globus" groesse={20} farbe={farben.primaer} />
|
||||
<Text style={styles.sprachButtonText}>
|
||||
{sprache.eigenname} {uebersetzt ? ' (übersetzt…)' : ''}
|
||||
</Text>
|
||||
<Ikone name="pfeilRechts" groesse={16} farbe={farben.textTertiaer} />
|
||||
</View>
|
||||
</Pressable>
|
||||
|
||||
{/* Kernaussage: Was will das Amt von mir? */}
|
||||
@@ -145,7 +150,7 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
<View style={{ marginTop: abstand.s }}>
|
||||
<GrossButton
|
||||
titel={liest ? 'Vorlesen stoppen' : 'Vorlesen'}
|
||||
symbol={liest ? '⏹️' : '🔊'}
|
||||
ikone={liest ? 'stopp' : 'vorlesen'}
|
||||
variante="sekundaer"
|
||||
onPress={vorlesen}
|
||||
/>
|
||||
@@ -162,7 +167,7 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
>
|
||||
{analyse.frist && (
|
||||
<Text style={styles.fristText}>
|
||||
📅 Frist: <Text style={styles.fett}>{formatiereDatum(analyse.frist.datum)}</Text>
|
||||
Frist: <Text style={styles.fett}>{formatiereDatum(analyse.frist.datum)}</Text>
|
||||
{'\n'}
|
||||
{analyse.frist.aktion}
|
||||
</Text>
|
||||
@@ -170,13 +175,13 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
{analyse.termin && (
|
||||
<>
|
||||
<Text style={styles.fristText}>
|
||||
🕐 Termin: <Text style={styles.fett}>{formatiereDatum(analyse.termin.datum)}</Text>
|
||||
Termin: <Text style={styles.fett}>{formatiereDatum(analyse.termin.datum)}</Text>
|
||||
{analyse.termin.uhrzeit ? ` um ${analyse.termin.uhrzeit} Uhr` : ''}
|
||||
{analyse.termin.ort ? `\n📍 ${analyse.termin.ort}` : ''}
|
||||
{analyse.termin.ort ? `\nOrt: ${analyse.termin.ort}` : ''}
|
||||
</Text>
|
||||
<GrossButton
|
||||
titel="Termin zum Kalender hinzufügen"
|
||||
symbol="🗓️"
|
||||
ikone="kalender"
|
||||
variante="sekundaer"
|
||||
onPress={kalenderExport}
|
||||
/>
|
||||
@@ -203,7 +208,11 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
accessibilityRole="checkbox"
|
||||
accessibilityState={{ checked: !!erledigt[i] }}
|
||||
>
|
||||
<Text style={styles.checkBox}>{erledigt[i] ? '☑️' : '⬜'}</Text>
|
||||
<Ikone
|
||||
name={erledigt[i] ? 'checkAn' : 'checkAus'}
|
||||
groesse={26}
|
||||
farbe={erledigt[i] ? farben.ampelGruen : farben.textTertiaer}
|
||||
/>
|
||||
<Text style={[styles.text, { flex: 1 }, erledigt[i] && styles.durchgestrichen]}>
|
||||
{punkt}
|
||||
</Text>
|
||||
@@ -229,13 +238,13 @@ export function AnalyseScreen({ navigation, route }: Props) {
|
||||
{analyse.antwort_noetig && (
|
||||
<GrossButton
|
||||
titel="Antwort erstellen"
|
||||
symbol="✍️"
|
||||
ikone="stift"
|
||||
onPress={() => navigation.navigate('Antwort', { briefId: brief.id })}
|
||||
/>
|
||||
)}
|
||||
|
||||
<View style={{ height: abstand.m }} />
|
||||
<GrossButton titel="Brief löschen" symbol="🗑️" variante="gefahr" onPress={loeschen} />
|
||||
<GrossButton titel="Brief löschen" ikone="muell" variante="gefahr" onPress={loeschen} />
|
||||
<View style={{ height: abstand.xl }} />
|
||||
|
||||
{/* Sprach-Auswahl-Dialog */}
|
||||
@@ -275,23 +284,19 @@ const styles = StyleSheet.create({
|
||||
zentriert: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
||||
karte: {
|
||||
backgroundColor: farben.flaeche,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.rand,
|
||||
borderRadius: 12,
|
||||
padding: abstand.m,
|
||||
marginTop: abstand.m,
|
||||
gap: abstand.s,
|
||||
...kartenSchatten,
|
||||
},
|
||||
// DIE Antwort der App — als "Textmarker"-Karte hervorgehoben (Markenzeichen)
|
||||
// DIE Antwort der App — dezent im Marken-Tint hervorgehoben
|
||||
karteWichtig: {
|
||||
backgroundColor: farben.markerHintergrund,
|
||||
borderRadius: 16,
|
||||
backgroundColor: farben.hervorhebung,
|
||||
borderRadius: 12,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.markerRand,
|
||||
borderColor: farben.hervorhebungRand,
|
||||
padding: abstand.m,
|
||||
marginTop: abstand.m,
|
||||
...kartenSchatten,
|
||||
},
|
||||
abschnittTitel: {
|
||||
fontSize: schrift.gross,
|
||||
@@ -310,22 +315,19 @@ const styles = StyleSheet.create({
|
||||
minHeight: 44,
|
||||
paddingVertical: 4,
|
||||
},
|
||||
checkBox: { fontSize: 24 },
|
||||
durchgestrichen: { textDecorationLine: 'line-through', color: farben.textSekundaer },
|
||||
begriffBlock: { marginBottom: abstand.s },
|
||||
begriff: { fontSize: schrift.basis, fontWeight: '700', color: farben.text },
|
||||
sprachButton: {
|
||||
marginTop: abstand.m,
|
||||
minHeight: TOUCH_TARGET,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.rand,
|
||||
borderRadius: 12,
|
||||
backgroundColor: farben.flaeche,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: abstand.m,
|
||||
...kartenSchatten,
|
||||
},
|
||||
sprachButtonText: { fontSize: schrift.basis, color: farben.text, fontWeight: '600' },
|
||||
sprachZeileInhalt: { flexDirection: 'row', alignItems: 'center', gap: abstand.s },
|
||||
sprachButtonText: { flex: 1, fontSize: schrift.basis, color: farben.text, fontWeight: '600' },
|
||||
modalHintergrund: {
|
||||
flex: 1,
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
@@ -333,7 +335,7 @@ const styles = StyleSheet.create({
|
||||
padding: abstand.l,
|
||||
},
|
||||
modalKarte: {
|
||||
backgroundColor: farben.hintergrund,
|
||||
backgroundColor: farben.flaeche,
|
||||
borderRadius: 14,
|
||||
padding: abstand.m,
|
||||
maxHeight: '75%',
|
||||
|
||||
@@ -146,7 +146,7 @@ export function AntwortScreen({ route }: Props) {
|
||||
|
||||
<GrossButton
|
||||
titel={text ? 'Neuen Entwurf erstellen' : 'Entwurf erstellen'}
|
||||
symbol="✨"
|
||||
ikone="funken"
|
||||
onPress={erzeugen}
|
||||
deaktiviert={!typ}
|
||||
laedt={laedt}
|
||||
@@ -173,8 +173,8 @@ export function AntwortScreen({ route }: Props) {
|
||||
accessibilityLabel="Brieftext"
|
||||
/>
|
||||
<View style={{ gap: abstand.s }}>
|
||||
<GrossButton titel="Als PDF exportieren" symbol="📄" onPress={alsPdf} />
|
||||
<GrossButton titel="Als Text teilen / kopieren" symbol="📤" variante="sekundaer" onPress={alsText} />
|
||||
<GrossButton titel="Als PDF exportieren" ikone="dokument" onPress={alsPdf} />
|
||||
<GrossButton titel="Als Text teilen / kopieren" ikone="teilen" variante="sekundaer" onPress={alsText} />
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -260,7 +260,7 @@ export function EinstellungenScreen({ navigation }: Props) {
|
||||
<View style={styles.trenner} />
|
||||
|
||||
<Text style={styles.abschnittTitel}>Daten löschen</Text>
|
||||
<GrossButton titel="Alle Daten löschen" symbol="🗑️" variante="gefahr" onPress={allesLoeschen} />
|
||||
<GrossButton titel="Alle Daten löschen" ikone="muell" variante="gefahr" onPress={allesLoeschen} />
|
||||
<View style={{ height: abstand.xl }} />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
+16
-26
@@ -18,29 +18,30 @@ import { holeConsent } from '../services/storage';
|
||||
import { berechneAmpel } from '../utils/ampel';
|
||||
import { formatiereDatum } from '../services/erinnerungen';
|
||||
import { GrossButton } from '../components/GrossButton';
|
||||
import { farben, schrift, abstand, kartenSchatten, TOUCH_TARGET } from '../theme';
|
||||
import { Ikone, IkonenName } from '../components/Ikone';
|
||||
import { farben, schrift, abstand, TOUCH_TARGET } from '../theme';
|
||||
|
||||
type Props = NativeStackScreenProps<RootStackParamList, 'Home'>;
|
||||
|
||||
/** Quadratische Navigations-Kachel: Symbol oben, Beschriftung darunter.
|
||||
/** Quadratische Navigations-Kachel: Icon oben, Beschriftung darunter.
|
||||
* (Löst das Platzproblem nebeneinanderstehender Text-Buttons.) */
|
||||
function Kachel({
|
||||
symbol,
|
||||
ikone,
|
||||
titel,
|
||||
onPress,
|
||||
}: {
|
||||
symbol: string;
|
||||
ikone: IkonenName;
|
||||
titel: string;
|
||||
onPress: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Pressable
|
||||
style={({ pressed }) => [styles.kachel, pressed && { opacity: 0.7 }]}
|
||||
style={({ pressed }) => [styles.kachel, pressed && { opacity: 0.65 }]}
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={titel}
|
||||
>
|
||||
<Text style={styles.kachelSymbol}>{symbol}</Text>
|
||||
<Ikone name={ikone} groesse={26} farbe={farben.primaer} />
|
||||
<Text style={styles.kachelTitel} numberOfLines={1}>
|
||||
{titel}
|
||||
</Text>
|
||||
@@ -105,7 +106,7 @@ export function HomeScreen({ navigation }: Props) {
|
||||
{ampel.text}
|
||||
</Text>
|
||||
</View>
|
||||
<Text style={styles.pfeil}>›</Text>
|
||||
<Ikone name="pfeilRechts" groesse={18} farbe={farben.textTertiaer} />
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
@@ -122,11 +123,11 @@ export function HomeScreen({ navigation }: Props) {
|
||||
contentContainerStyle={styles.inhalt}
|
||||
ListHeaderComponent={
|
||||
<View style={styles.kopf}>
|
||||
<GrossButton titel="Brief scannen" symbol="📷" onPress={scanStarten} />
|
||||
<GrossButton titel="Brief scannen" ikone="kamera" onPress={scanStarten} />
|
||||
<View style={styles.reihe}>
|
||||
<Kachel symbol="📖" titel="Glossar" onPress={() => navigation.navigate('Glossar')} />
|
||||
<Kachel ikone="buch" titel="Glossar" onPress={() => navigation.navigate('Glossar')} />
|
||||
<Kachel
|
||||
symbol="⚙️"
|
||||
ikone="zahnrad"
|
||||
titel="Einstellungen"
|
||||
onPress={() => navigation.navigate('Einstellungen')}
|
||||
/>
|
||||
@@ -149,7 +150,7 @@ export function HomeScreen({ navigation }: Props) {
|
||||
ListEmptyComponent={
|
||||
briefe.length === 0 ? (
|
||||
<View style={styles.leerBox}>
|
||||
<Text style={styles.leerSymbol}>📬</Text>
|
||||
<Ikone name="brief" groesse={48} farbe={farben.textTertiaer} />
|
||||
<Text style={styles.leerTitel}>Noch keine Briefe</Text>
|
||||
<Text style={styles.leer}>
|
||||
Scannen Sie Ihren ersten Behördenbrief —{'\n'}in einer Minute
|
||||
@@ -173,16 +174,12 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
minHeight: TOUCH_TARGET + 22,
|
||||
backgroundColor: farben.flaeche,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.rand,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: abstand.s,
|
||||
gap: 4,
|
||||
...kartenSchatten,
|
||||
gap: 6,
|
||||
},
|
||||
kachelSymbol: { fontSize: 26 },
|
||||
kachelTitel: { fontSize: schrift.klein + 1, fontWeight: '600', color: farben.primaer },
|
||||
abschnittsLabel: {
|
||||
marginTop: abstand.m,
|
||||
@@ -194,8 +191,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
suche: {
|
||||
backgroundColor: farben.flaeche,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.rand,
|
||||
borderRadius: 12,
|
||||
padding: abstand.s,
|
||||
fontSize: schrift.basis,
|
||||
@@ -206,21 +201,16 @@ const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: farben.flaeche,
|
||||
borderRadius: 14,
|
||||
borderWidth: 1,
|
||||
borderColor: farben.rand,
|
||||
borderRadius: 12,
|
||||
borderLeftWidth: 6,
|
||||
padding: abstand.m,
|
||||
marginBottom: abstand.s,
|
||||
gap: abstand.s,
|
||||
...kartenSchatten,
|
||||
},
|
||||
kartenTitel: { fontSize: schrift.basis, fontWeight: '700', color: farben.text },
|
||||
kartenUntertitel: { fontSize: schrift.klein, color: farben.textSekundaer, marginTop: 2 },
|
||||
kartenAmpelText: { fontSize: schrift.klein, fontWeight: '600', marginTop: 2 },
|
||||
pfeil: { fontSize: 32, color: farben.textSekundaer },
|
||||
leerBox: { alignItems: 'center', marginTop: abstand.xl, gap: abstand.xs },
|
||||
leerSymbol: { fontSize: 52 },
|
||||
leerBox: { alignItems: 'center', marginTop: abstand.xl, gap: abstand.s },
|
||||
leerTitel: { fontSize: schrift.gross, fontWeight: '700', color: farben.text },
|
||||
leer: {
|
||||
textAlign: 'center',
|
||||
|
||||
@@ -182,9 +182,9 @@ export function ScanScreen({ navigation }: Props) {
|
||||
Fotografieren Sie den Brief gut beleuchtet und von oben. Der ganze Text
|
||||
muss auf dem Foto sein.
|
||||
</Text>
|
||||
<GrossButton titel="Foto aufnehmen" symbol="📷" onPress={fotoAufnehmen} />
|
||||
<GrossButton titel="Aus Galerie wählen" symbol="🖼️" variante="sekundaer" onPress={ausGalerie} />
|
||||
<GrossButton titel="PDF hochladen" symbol="📄" variante="sekundaer" onPress={pdfWaehlen} />
|
||||
<GrossButton titel="Foto aufnehmen" ikone="kamera" onPress={fotoAufnehmen} />
|
||||
<GrossButton titel="Aus Galerie wählen" ikone="galerie" variante="sekundaer" onPress={ausGalerie} />
|
||||
<GrossButton titel="PDF hochladen" ikone="dokument" variante="sekundaer" onPress={pdfWaehlen} />
|
||||
{NUTZT_PROXY && (
|
||||
<Text style={styles.kontingent}>
|
||||
{kontingentLeer
|
||||
|
||||
Reference in new issue
Block a user