diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 4a666ae..30f8b78 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -23,6 +23,7 @@
"expo-font": "~14.0.11",
"expo-linear-gradient": "~15.0.8",
"expo-status-bar": "~3.0.9",
+ "lucide-react-native": "^1.12.0",
"nativewind": "^4.2.1",
"react": "19.1.0",
"react-dom": "19.1.0",
@@ -11106,6 +11107,17 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lucide-react-native": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/lucide-react-native/-/lucide-react-native-1.12.0.tgz",
+ "integrity": "sha512-qw9fMGWTFiGNHVoYOv2N5FzXJaP1/UwVbJAbATNGzJQPGWXVQXITjZUpTjZ/QWLWPz4tBYobn+dhDWGRePLqvg==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-native": "*",
+ "react-native-svg": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0"
+ }
+ },
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 43a8f61..c9e5431 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -32,6 +32,7 @@
"expo-font": "~14.0.11",
"expo-linear-gradient": "~15.0.8",
"expo-status-bar": "~3.0.9",
+ "lucide-react-native": "^1.12.0",
"nativewind": "^4.2.1",
"react": "19.1.0",
"react-dom": "19.1.0",
diff --git a/frontend/src/components/AddFoodModal.tsx b/frontend/src/components/AddFoodModal.tsx
index 543c8be..bf7f9f0 100644
--- a/frontend/src/components/AddFoodModal.tsx
+++ b/frontend/src/components/AddFoodModal.tsx
@@ -59,7 +59,7 @@ export function AddFoodModal({ visible, onClose }: Props) {
placeholder="e.g. Milk, Wheat, Soy..."
chipClassName='bg-remetra-burgundy'
chipTextClassName='text-white'
- removeTextClassName='text-white'
+ removeIconColor='#ffffff'
onAdd={(ing) => setIngredients((prev) => [...prev, ing])}
onRemove={(i) => setIngredients((prev) => prev.filter((_, idx) => idx !== i))}
/>
diff --git a/frontend/src/components/BarcodeScannerScreen.tsx b/frontend/src/components/BarcodeScannerScreen.tsx
index f2e9abf..df4c653 100644
--- a/frontend/src/components/BarcodeScannerScreen.tsx
+++ b/frontend/src/components/BarcodeScannerScreen.tsx
@@ -1,6 +1,7 @@
import { View, Text, TouchableOpacity, TextInput, StyleSheet } from "react-native";
import { useNavigation, useRoute } from "@react-navigation/native";
import { CameraView, useCameraPermissions } from "expo-camera";
+import { ArrowLeft } from "lucide-react-native";
import { useState, useRef } from "react";
import { useBankStore } from "../store/bankStore";
@@ -91,7 +92,10 @@ export const BarcodeScannerScreen = () => {
Point at a barcode
navigation.goBack()}>
- ← Cancel
+
+
+ Cancel
+
{scanned && (
setScanned(false)}>
diff --git a/frontend/src/components/FoodLogForm.tsx b/frontend/src/components/FoodLogForm.tsx
index 860386a..7d0359e 100644
--- a/frontend/src/components/FoodLogForm.tsx
+++ b/frontend/src/components/FoodLogForm.tsx
@@ -7,6 +7,7 @@ import { useNavigation } from '@react-navigation/native';
import { useUIStore } from "../store/uiStore";
import { useState, useEffect } from "react";
import { View, Text, TouchableOpacity, TextInput } from "react-native";
+import { ArrowLeft, Camera } from "lucide-react-native";
import { LogDateTimePicker } from "./LogDateTimePicker";
interface FoodLogFormProps {
@@ -96,14 +97,19 @@ export const FoodLogForm: React.FC = ({ onSubmit, onBack, onCl
return (
- {
- if (!selectedFood && !isCustom) {
- onBack()
- } else {
- setIsCustom(false); setSearchQuery(""); setSelectedFood(null)
- }
- }}>
- ← Back
+ {
+ if (!selectedFood && !isCustom) {
+ onBack()
+ } else {
+ setIsCustom(false); setSearchQuery(""); setSelectedFood(null)
+ }
+ }}
+ className="flex-row items-center gap-1.5 mb-4"
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ >
+
+ Back
@@ -111,13 +117,15 @@ export const FoodLogForm: React.FC = ({ onSubmit, onBack, onCl
{!selectedFood && !isCustom && (
{
onCloseModal();
setTimeout(() => navigation.navigate('BarcodeScanner'), 300);
}}
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ accessibilityLabel="Scan Barcode"
>
- Scan Barcode
+
)}
@@ -187,7 +195,7 @@ export const FoodLogForm: React.FC = ({ onSubmit, onBack, onCl
placeholder="Add Ingredients..."
chipClassName='bg-remetra-burgundy/80'
chipTextClassName='text-white'
- removeTextClassName='text-white'
+ removeIconColor='#ffffff'
onAdd={(ing) => setCustomIngredients((prev) => [...prev, ing])}
onRemove={(i) => setCustomIngredients((prev) => prev.filter((_, idx) => idx !== i))}
/>
diff --git a/frontend/src/components/GenericChipComponent.tsx b/frontend/src/components/GenericChipComponent.tsx
index 2fc6a9d..f45fb51 100644
--- a/frontend/src/components/GenericChipComponent.tsx
+++ b/frontend/src/components/GenericChipComponent.tsx
@@ -5,6 +5,7 @@ import {
TextInput,
TouchableOpacity,
} from "react-native";
+import { X } from "lucide-react-native";
interface ChipsProps {
items: string[];
@@ -14,7 +15,7 @@ interface ChipsProps {
onRemove: (index: number) => void;
chipClassName?: string;
chipTextClassName?: string;
- removeTextClassName?: string;
+ removeIconColor?: string;
}
export const Chips: React.FC = ({
@@ -25,7 +26,7 @@ export const Chips: React.FC = ({
onRemove,
chipClassName = "bg-neutral-200",
chipTextClassName = "text-neutral-700",
- removeTextClassName = "text-neutral-500"
+ removeIconColor = "#737373"
}) => {
const [input, setInput] = useState("");
@@ -45,8 +46,8 @@ export const Chips: React.FC = ({
className={`flex-row items-center rounded-full py-1.5 px-3 gap-1.5 ${chipClassName}`}
>
{item}
- onRemove(i)}>
- ✕
+ onRemove(i)} hitSlop={{ top: 6, bottom: 6, left: 6, right: 6 }}>
+
))}
diff --git a/frontend/src/components/ItemBank.tsx b/frontend/src/components/ItemBank.tsx
index 41d632f..7a57de9 100644
--- a/frontend/src/components/ItemBank.tsx
+++ b/frontend/src/components/ItemBank.tsx
@@ -1,4 +1,5 @@
import { View, Text, TouchableOpacity } from 'react-native';
+import { X } from 'lucide-react-native';
interface ItemBankProps {
title: string;
@@ -36,8 +37,9 @@ export function ItemBank({
onRemove(item.id)}
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ className="mr-2"
>
- ✕
+
{item.name}
diff --git a/frontend/src/components/LogEntryModal.tsx b/frontend/src/components/LogEntryModal.tsx
index aa5d32c..834eb88 100644
--- a/frontend/src/components/LogEntryModal.tsx
+++ b/frontend/src/components/LogEntryModal.tsx
@@ -1,5 +1,6 @@
import { Modal, ScrollView, View, TouchableOpacity, Text } from "react-native";
import { useState, useEffect } from "react";
+import { X, Utensils, Stethoscope } from "lucide-react-native";
import { LogEntry, ModalStep } from "../types/logs";
import { FoodLogForm } from "./FoodLogForm";
@@ -49,8 +50,8 @@ const LogEntryModal: React.FC = ({ visible, onClose, onLogEn
onStartShouldSetResponder={() => true}
>
-
- ✕
+
+
@@ -65,7 +66,7 @@ const LogEntryModal: React.FC = ({ visible, onClose, onLogEn
className="w-full flex-row items-center gap-4 border border-remetra-burgundy rounded-2xl p-5 bg-remetra-orange/10"
onPress={() => setStep("food")}
>
- 🍽
+
Food
@@ -73,7 +74,7 @@ const LogEntryModal: React.FC = ({ visible, onClose, onLogEn
className="w-full flex-row items-center gap-4 border border-remetra-burgundy rounded-2xl p-5 bg-remetra-orange/10"
onPress={() => setStep("symptom")}
>
- 🩺
+
Symptom
diff --git a/frontend/src/components/SymptomCard.tsx b/frontend/src/components/SymptomCard.tsx
index c4aa06e..fb3141b 100644
--- a/frontend/src/components/SymptomCard.tsx
+++ b/frontend/src/components/SymptomCard.tsx
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
+import { Check } from 'lucide-react-native';
import { symptomLogService } from '../api/symptom_log_service';
import { LogDateTimePicker } from './LogDateTimePicker';
import { SymptomTimelineEntry } from '../types/timeline';
@@ -142,7 +143,7 @@ export function SymptomCard({
hasDuration ? 'bg-remetra-burgundy border-remetra-burgundy' : 'bg-white border-remetra-border'
}`}
>
- {hasDuration ? ✓ : null}
+ {hasDuration ? : null}
Duration (minutes)
diff --git a/frontend/src/components/SymptomLogForm.tsx b/frontend/src/components/SymptomLogForm.tsx
index 78a2f8b..23fc352 100644
--- a/frontend/src/components/SymptomLogForm.tsx
+++ b/frontend/src/components/SymptomLogForm.tsx
@@ -4,6 +4,7 @@ import { symptomLogService } from "../api/symptom_log_service";
import { useAuthStore } from "../store/useAuthStore";
import { useState } from "react";
import { View, Text, TouchableOpacity, TextInput } from "react-native";
+import { ArrowLeft } from "lucide-react-native";
import { Dropdown } from "react-native-element-dropdown";
import { LogDateTimePicker } from "./LogDateTimePicker";
import { sensationOptions, locationOptions } from "../types/symptomOptions";
@@ -100,17 +101,20 @@ export const SymptomLogForm: React.FC = ({ onSubmit, onBack
return (
- {
- if (!selectedSymptom && !isCustom) {
- onBack()
- } else {
- setIsCustom(false); setSearchQuery(""); setSelectedSymptom(null);
- setCustomSensation(""); setCustomLocation("");
- }
- onBack
- }
- }>
- ← Back
+ {
+ if (!selectedSymptom && !isCustom) {
+ onBack()
+ } else {
+ setIsCustom(false); setSearchQuery(""); setSelectedSymptom(null);
+ setCustomSensation(""); setCustomLocation("");
+ }
+ }}
+ className="flex-row items-center gap-1.5 mb-4"
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ >
+
+ Back
diff --git a/frontend/src/navigation/MainTabs.tsx b/frontend/src/navigation/MainTabs.tsx
index 69c8748..f5812d9 100644
--- a/frontend/src/navigation/MainTabs.tsx
+++ b/frontend/src/navigation/MainTabs.tsx
@@ -1,11 +1,12 @@
import React from 'react';
-import { View, Text } from 'react-native';
+import { View } from 'react-native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { TimelineScreen } from '../screens/main/TimelineScreen';
import { AnalysisScreen } from '../screens/main/AnalysisScreen';
import { ProfileScreen } from '../screens/main/ProfileScreen';
import LogEntryModal from '../components/LogEntryModal';
import { useUIStore } from '../store/uiStore';
+import { ClipboardList, ChartColumn, User, type LucideIcon } from 'lucide-react-native';
export type MainTabParamList = {
History: undefined;
@@ -15,10 +16,13 @@ export type MainTabParamList = {
const Tab = createBottomTabNavigator();
-function TabIcon({ emoji, focused }: { emoji: string; focused: boolean }) {
+const TAB_ACTIVE_COLOR = '#B8624F';
+const TAB_INACTIVE_COLOR = '#b2939b';
+
+function TabIcon({ Icon, focused }: { Icon: LucideIcon; focused: boolean }) {
return (
- {emoji}
+
);
}
@@ -54,7 +58,7 @@ export function MainTabs() {
component={TimelineScreen}
options={{
tabBarIcon: ({ focused }) => (
-
+
),
}}
/>
@@ -63,7 +67,7 @@ export function MainTabs() {
component={AnalysisScreen}
options={{
tabBarIcon: ({ focused }) => (
-
+
),
}}
/>
@@ -72,7 +76,7 @@ export function MainTabs() {
component={ProfileScreen}
options={{
tabBarIcon: ({ focused }) => (
-
+
),
}}
/>
diff --git a/frontend/src/screens/main/AboutScreen.tsx b/frontend/src/screens/main/AboutScreen.tsx
index 9a61107..0528286 100644
--- a/frontend/src/screens/main/AboutScreen.tsx
+++ b/frontend/src/screens/main/AboutScreen.tsx
@@ -1,5 +1,13 @@
import React from 'react';
import { View, Text, TouchableOpacity, ScrollView, Linking } from 'react-native';
+import {
+ HeartPlus,
+ NotebookPen,
+ Search,
+ ChartColumn,
+ ChevronRight,
+ type LucideIcon,
+} from 'lucide-react-native';
import { BackgroundGradient } from '../../components/BackgroundGradient';
const CONTACT_EMAIL = 'hello@remetra.app';
@@ -12,7 +20,7 @@ export function AboutScreen() {
{/* Hero */}
- ⚕️
+
REMETRA
@@ -35,9 +43,9 @@ export function AboutScreen() {
{/* How it works */}
-
-
-
+
+
+
{/* Links */}
@@ -87,10 +95,10 @@ function SectionDivider({ label }: { label: string }) {
);
}
-function InfoRow({ emoji, label }: { emoji: string; label: string }) {
+function InfoRow({ Icon, label }: { Icon: LucideIcon; label: string }) {
return (
- {emoji}
+
{label}
);
@@ -103,7 +111,7 @@ function LinkRow({ label, onPress }: { label: string; onPress: () => void }) {
className="bg-white/70 rounded-xl p-4 flex-row items-center gap-3"
>
{label}
- ›
+
);
}
diff --git a/frontend/src/screens/main/CorrelationsScreen.tsx b/frontend/src/screens/main/CorrelationsScreen.tsx
index ca59993..eb47471 100644
--- a/frontend/src/screens/main/CorrelationsScreen.tsx
+++ b/frontend/src/screens/main/CorrelationsScreen.tsx
@@ -1,4 +1,5 @@
import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator, TextInput } from 'react-native';
+import { ArrowLeft } from 'lucide-react-native';
import { useEffect, useMemo } from 'react';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { BackgroundGradient } from '../../components/BackgroundGradient';
@@ -43,8 +44,13 @@ export function CorrelationsScreen({ navigation, route }: Props) {
{/* Header */}
- navigation.goBack()} style={{ marginBottom: 8 }}>
- ← Back
+ navigation.goBack()}
+ style={{ marginBottom: 8, flexDirection: 'row', alignItems: 'center', gap: 6 }}
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ >
+
+ Back
diff --git a/frontend/src/screens/main/EditConditionsScreen.tsx b/frontend/src/screens/main/EditConditionsScreen.tsx
index 48672a7..3164ad4 100644
--- a/frontend/src/screens/main/EditConditionsScreen.tsx
+++ b/frontend/src/screens/main/EditConditionsScreen.tsx
@@ -46,7 +46,7 @@ export function EditConditionsScreen() {
placeholder="Add condition..."
chipClassName='bg-remetra-burgundy opacity-90'
chipTextClassName='font-semibold text-remetra-surface-accent'
- removeTextClassName='font-semibold text-remetra-surface-accent'
+ removeIconColor='#fff5f0'
onAdd={(item) => setDisease((prev) => [...prev, item])}
onRemove={(i) =>
setDisease((prev) => prev.filter((_, idx) => idx !== i))
diff --git a/frontend/src/screens/main/EditMedicationsScreen.tsx b/frontend/src/screens/main/EditMedicationsScreen.tsx
index 6a1a432..c41ef6c 100644
--- a/frontend/src/screens/main/EditMedicationsScreen.tsx
+++ b/frontend/src/screens/main/EditMedicationsScreen.tsx
@@ -46,7 +46,7 @@ export function EditMedicationsScreen() {
placeholder="Add condition..."
chipClassName='bg-remetra-burgundy opacity-90'
chipTextClassName='font-semibold text-remetra-surface-accent'
- removeTextClassName='font-semibold text-remetra-surface-accent'
+ removeIconColor='#fff5f0'
onAdd={(item) => setMedication((prev) => [...prev, item])}
onRemove={(i) =>
setMedication((prev) => prev.filter((_, idx) => idx !== i))
diff --git a/frontend/src/screens/main/ProfileScreen.tsx b/frontend/src/screens/main/ProfileScreen.tsx
index efd72c7..46dec2a 100644
--- a/frontend/src/screens/main/ProfileScreen.tsx
+++ b/frontend/src/screens/main/ProfileScreen.tsx
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
import { useNavigation, useFocusEffect } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
+import { Info, ChevronRight, type LucideIcon } from 'lucide-react-native';
import { BackgroundGradient } from '../../components/BackgroundGradient';
import { useAuthStore } from '../../store/useAuthStore';
import type { MainStackParamList } from '../../navigation/stacks/MainStack';
@@ -68,7 +69,7 @@ export function ProfileScreen() {
navigation.navigate('About')}
/>
@@ -97,11 +98,11 @@ function SectionDivider({ label }: { label: string }) {
}
function ActionRow({
- emoji,
+ Icon,
label,
onPress,
}: {
- emoji: string;
+ Icon: LucideIcon;
label: string;
onPress: () => void;
}) {
@@ -110,9 +111,9 @@ function ActionRow({
onPress={onPress}
className="bg-white/70 rounded-xl p-4 flex-row items-center gap-3"
>
- {emoji}
+
{label}
- ›
+
);
}
@@ -147,7 +148,7 @@ function EditableRow({
{value}
- ›
+
);
@@ -168,7 +169,7 @@ function EditableChipRow({
{label.toUpperCase()}
- ›
+
{items.length === 0 ? (
—
diff --git a/frontend/src/screens/main/TimelineScreen.tsx b/frontend/src/screens/main/TimelineScreen.tsx
index 6a3279b..c46f223 100644
--- a/frontend/src/screens/main/TimelineScreen.tsx
+++ b/frontend/src/screens/main/TimelineScreen.tsx
@@ -7,6 +7,7 @@ import {
TouchableOpacity,
View,
} from 'react-native';
+import { ClipboardList } from 'lucide-react-native';
import { BackgroundGradient } from '../../components/BackgroundGradient';
import { FoodCard } from '../../components/FoodCard';
import { SymptomCard } from '../../components/SymptomCard';
@@ -178,7 +179,7 @@ export function TimelineScreen() {
Symptom
- Tap a card to edit
+ Tap a card to edit
{/* Content */}
@@ -198,9 +199,9 @@ export function TimelineScreen() {
) : entries.length === 0 ? (
- 📋
+
No logs yet
-
+
Tap + Add Log to record your first food or symptom entry.
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index 259320f..e3b349e 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -18,7 +18,7 @@ module.exports = {
'remetra-terracotta': '#ca5e5e', // chart bar fill
'remetra-mauve': '#b2939b', // screen headers, low intensity, spinners
'remetra-espresso': '#5C2E14', // Dark text on gradient
- 'remetra-warm-brown': '#7A4F35', // Warmer brown for secondary text
+ 'remetra-warm-brown': '#7A4F35', // Warmer brown for secondary
// Structural / semantic
'remetra-surface': '#fafafa', // input & list-item backgrounds
'remetra-border': '#ccc', // generic input / card borders