Description
The floating "+" button disappears from the main screen after dismissing the /new modal (for any form type). The button only reappears when switching to a different tab and back.
Affected Flows
This bug affects ALL four form flows, not just the receipt flow:
| Form |
Error Handling |
Severity |
| Receipt |
console.error only - no user feedback |
High |
| Statement |
console.error only - no user feedback |
High |
| Transaction (Form) |
Shows Alert.alert but button still disappears |
Medium |
| Text |
Shows Alert.alert but button still disappears |
Medium |
Steps to Reproduce
Receipt Flow (High Severity)
- Tap the floating "+" button
- Select "Receipt" option
- Choose an image from library
- Tap "Extract"
- Wait for extraction to fail
- Dismiss the modal (swipe down)
- Observe: "+" button is missing, no error feedback shown
Statement Flow (High Severity)
- Tap the floating "+" button
- Select "Statement" option
- Choose a CSV file
- Tap "Extract"
- Wait for extraction to fail
- Dismiss the modal (swipe down)
- Observe: "+" button is missing, no error feedback shown
Form Flow (Medium Severity)
- Tap the floating "+" button
- Select "Form" option
- Fill in form fields
- Tap "Save"
- If API error occurs, alert is shown
- Dismiss alert and then dismiss modal
- Observe: "+" button is missing
Text Flow (Medium Severity)
- Tap the floating "+" button
- Select "Text" option
- Enter some text
- Tap "Extract"
- If error occurs, alert is shown
- Dismiss alert and then dismiss modal
- Observe: "+" button is missing
Alternative Reproduction (Any Flow)
- Tap the floating "+" button
- Select any option
- Immediately dismiss the modal (swipe down without doing anything)
- Observe: "+" button is missing
Environment
- Device: iPhone 16e Simulator
- Platform: iOS
Root Cause Analysis
The issue is caused by the overlay state not being reset when the modal is dismissed.
Code Flow
- User taps "+" button →
useOverlayStore.show() is called → isVisible: true
- User taps any option →
router.push("/new?type=...") AND hide() is called (add-button.tsx:27-29)
- Modal opens → pathname changes to
/new
- User encounters error or dismisses modal
- User manually dismisses modal (swipe down gesture on iOS)
- User returns to "/" but the
AddButton component has stale animation state
Why Tab Switching Fixes It
Switching tabs causes a full navigation state change, forcing React to properly re-render the entire protected layout and remount components with fresh state.
Relevant Files
| File |
Issue |
app/(protected)/_layout.tsx:28 |
Determines button visibility but doesn't reset overlay state on route change |
app/(protected)/_layout.tsx:82 |
Renders {showAddButton && <AddButton />} |
components/add-button.tsx:43-54 |
Animation tied to useOverlayStore.isVisible |
components/receipt-form.tsx:81-83 |
Error handler only logs, no alert |
components/statement-form.tsx:62-64 |
Error handler only logs, no alert |
components/transaction-form.tsx:101-104 |
Has alert but button still disappears |
components/text-transaction-input.tsx:37-43 |
Has alert but button still disappears |
store/overlayStore.ts |
Zustand store controlling overlay visibility |
Suggested Fix
Primary Fix (Resolves button disappearing for all flows)
Add a useEffect in app/(protected)/_layout.tsx to reset the overlay state when the pathname changes back to a main route:
// Reset overlay state when returning to main routes (e.g., after modal dismiss)
useEffect(() => {
if (ADD_BUTTON_ROUTES.some((route) => pathname === route)) {
hide();
}
}, [pathname, hide]);
Secondary Fix (Improve error UX for Receipt and Statement forms)
Add proper error alerts in receipt-form.tsx and statement-form.tsx:
// receipt-form.tsx lines 81-83
onError: (error) => {
Alert.alert("Extraction Failed", error.message || "Could not extract transactions from the receipt. Please try again.");
}
// statement-form.tsx lines 62-64
onError: (error) => {
Alert.alert("Upload Failed", error.message || "Could not process the statement. Please try again.");
}
Labels
bug, iOS, navigation, UI
Description
The floating "+" button disappears from the main screen after dismissing the
/newmodal (for any form type). The button only reappears when switching to a different tab and back.Affected Flows
This bug affects ALL four form flows, not just the receipt flow:
console.erroronly - no user feedbackconsole.erroronly - no user feedbackAlert.alertbut button still disappearsAlert.alertbut button still disappearsSteps to Reproduce
Receipt Flow (High Severity)
Statement Flow (High Severity)
Form Flow (Medium Severity)
Text Flow (Medium Severity)
Alternative Reproduction (Any Flow)
Environment
Root Cause Analysis
The issue is caused by the overlay state not being reset when the modal is dismissed.
Code Flow
useOverlayStore.show()is called →isVisible: truerouter.push("/new?type=...")ANDhide()is called (add-button.tsx:27-29)/newAddButtoncomponent has stale animation stateWhy Tab Switching Fixes It
Switching tabs causes a full navigation state change, forcing React to properly re-render the entire protected layout and remount components with fresh state.
Relevant Files
app/(protected)/_layout.tsx:28app/(protected)/_layout.tsx:82{showAddButton && <AddButton />}components/add-button.tsx:43-54useOverlayStore.isVisiblecomponents/receipt-form.tsx:81-83components/statement-form.tsx:62-64components/transaction-form.tsx:101-104components/text-transaction-input.tsx:37-43store/overlayStore.tsSuggested Fix
Primary Fix (Resolves button disappearing for all flows)
Add a
useEffectinapp/(protected)/_layout.tsxto reset the overlay state when the pathname changes back to a main route:Secondary Fix (Improve error UX for Receipt and Statement forms)
Add proper error alerts in
receipt-form.tsxandstatement-form.tsx:Labels
bug, iOS, navigation, UI