From 3b26525b8070602cc97939bd08adbd1285bfec0d Mon Sep 17 00:00:00 2001 From: aleqsio Date: Thu, 27 Aug 2026 17:03:43 +0200 Subject: [PATCH] Swap the grind guide for a water guide Grind size is already on every method screen and in the compare table, so the standalone guide repeated what the app said elsewhere. Water is the part the app never covered: temperature bands, what the minerals do, and why filtering chlorine comes before anything else. Co-Authored-By: Claude Opus 5 --- src/app/(tabs)/compare.tsx | 6 +- src/app/_layout.tsx | 2 +- src/app/grind.tsx | 87 ------------------------- src/app/water.tsx | 126 +++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 91 deletions(-) delete mode 100644 src/app/grind.tsx create mode 100644 src/app/water.tsx diff --git a/src/app/(tabs)/compare.tsx b/src/app/(tabs)/compare.tsx index 7c4fef7..9f3bc2e 100644 --- a/src/app/(tabs)/compare.tsx +++ b/src/app/(tabs)/compare.tsx @@ -61,13 +61,13 @@ export default function CompareScreen() { ))} - + ({ opacity: pressed ? 0.75 : 1 })}> - Grind guide + Water - What fine, medium and coarse actually mean + Temperature and minerals, the other 98% of the cup diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 69a9531..55101f9 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -21,7 +21,7 @@ export default function RootLayout() { - + diff --git a/src/app/grind.tsx b/src/app/grind.tsx deleted file mode 100644 index ae0dbcd..0000000 --- a/src/app/grind.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { Stack } from 'expo-router'; -import { StyleSheet, View } from 'react-native'; - -import { Card, Chip, Eyebrow, Rule, Screen, Type } from '@/components/ui'; -import { Spacing } from '@/constants/theme'; -import { GRIND_NOTES, GRIND_SCALE, METHODS } from '@/data/methods'; -import { usePalette } from '@/hooks/use-palette'; - -export default function GrindScreen() { - const c = usePalette(); - return ( - <> - - - - Particle size - Grind - - Grind size sets how fast water can move through the bed. Everything else — dose, - temperature, time — is a correction on top of it. - - - - - {GRIND_SCALE.map((g, i) => { - const users = METHODS.filter((m) => m.grind === g); - return ( - - {i > 0 && } - - - - {Array.from({ length: 5 - i }, (_, d) => ( - - ))} - - - {g} - - - - {GRIND_NOTES[g]} - - {users.length > 0 && ( - - {users.map((m) => ( - - {m.name} - - ))} - - )} - - - ); - })} - - - - Rule of thumb - - Sour and thin means the water left too early — go finer. Harsh and drying means it - stayed too long — go coarser. Change one thing at a time. - - - - - ); -} - -const styles = StyleSheet.create({ - masthead: { gap: Spacing.two, paddingTop: Spacing.two }, - scale: { paddingVertical: 0 }, - step: { paddingVertical: Spacing.four, gap: Spacing.two }, - stepHead: { flexDirection: 'row', alignItems: 'center', gap: Spacing.three }, - dots: { flexDirection: 'row', alignItems: 'center', gap: 2, width: 46 }, - dot: { borderRadius: 4 }, - stepName: { textTransform: 'capitalize' }, - users: { flexDirection: 'row', flexWrap: 'wrap', gap: Spacing.two, paddingTop: Spacing.one }, - note: { gap: Spacing.two }, -}); diff --git a/src/app/water.tsx b/src/app/water.tsx new file mode 100644 index 0000000..4eefd28 --- /dev/null +++ b/src/app/water.tsx @@ -0,0 +1,126 @@ +import { Stack } from 'expo-router'; +import { StyleSheet, View } from 'react-native'; + +import { Card, Chip, Eyebrow, Rule, Screen, Type } from '@/components/ui'; +import { Spacing } from '@/constants/theme'; +import { usePalette } from '@/hooks/use-palette'; + +/* Temperature bands, coolest first. The chips name the methods that sit in + each band, which is the same shape the grind guide used. */ +const BANDS = [ + { + range: '80–88°C', + name: 'cool', + note: 'Light roasts stay sweet instead of turning sharp. Slower to extract, so give it time.', + methods: ['AeroPress'], + }, + { + range: '90–94°C', + name: 'standard', + note: 'Where most recipes land. Hot enough to pull sugars, not so hot it strips the cup.', + methods: ['V60', 'French press'], + }, + { + range: '95–100°C', + name: 'hot', + note: 'Dark roasts and stale beans need the extra energy. Anything fresh will taste harsh.', + methods: [], + }, +]; + +const MINERALS = [ + ['Calcium + magnesium', 'Carry flavour. Too little and the cup reads flat and watery.'], + ['Bicarbonate', 'Buffers acidity. Too much and everything tastes dull and chalky.'], + ['Chlorine', 'Ruins a cup on its own. Filter it out before anything else.'], +]; + +export default function WaterScreen() { + const c = usePalette(); + return ( + <> + + + + 98% of the cup + Water + + Coffee is almost entirely water, so the water decides how much of the bean you ever + taste. Temperature sets the pace, minerals decide what comes through. + + + + + {BANDS.map((band, i) => ( + + {i > 0 && } + + + + + + + {band.range} + + {band.name} + + + + + {band.note} + + {band.methods.length > 0 && ( + + {band.methods.map((m) => ( + + {m} + + ))} + + )} + + + ))} + + + + What is in it + {MINERALS.map(([label, text]) => ( + + {label} + + {text} + + + ))} + + + + ); +} + +const styles = StyleSheet.create({ + masthead: { gap: Spacing.two, paddingTop: Spacing.two }, + bands: { paddingVertical: 0 }, + band: { paddingVertical: Spacing.four, gap: Spacing.two }, + bandHead: { flexDirection: 'row', alignItems: 'center', gap: Spacing.three }, + gauge: { + width: 14, + height: 34, + borderWidth: 1, + borderRadius: 3, + justifyContent: 'flex-end', + overflow: 'hidden', + }, + gaugeFill: { width: '100%' }, + bandTitle: { gap: 2 }, + methods: { flexDirection: 'row', flexWrap: 'wrap', gap: Spacing.two, paddingTop: Spacing.one }, + note: { gap: Spacing.three }, + mineral: { gap: 2 }, +});