Skip to content

fix(ui/navigation): pop the sheet entry when a drag dismisses it - #1278

Merged
bmc08gt merged 1 commit into
code/cashfrom
claude/sheet-dismiss-tab-bar-4bfc67
Aug 20, 2026
Merged

fix(ui/navigation): pop the sheet entry when a drag dismisses it#1278
bmc08gt merged 1 commit into
code/cashfrom
claude/sheet-dismiss-tab-bar-4bfc67

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

The bug

Drag a sheet that shows over the v2 tab bar closed (region selection from the wallet tab) and the tab bar doesn't come back — it stays hidden until you tap the screen, and that first tap is swallowed rather than doing what you aimed it at.

Root cause

UnstyledBottomSheet (compose-unstyled) has no dismissal callback. That wiring existed when the scene used Material3's ModalBottomSheet — its onDismissRequest popped the nav entry once a user drag settled the sheet to Hidden — and nothing replaced it when the scene was rebuilt on the unstyled sheet in 6e49a91.

So a drag-dismiss hides the sheet without telling anyone:

  • the AppRoute.Main.Sheet(...) entry stays on the backstack, so navigator.currentRouteKey still resolves to the sheet → topTab == nullAppNavigationBar keeps the tab bar hidden;
  • the scene's full-size scrim is still composed (just animated to alpha 0), so it eats every touch until one lands on its noRippleClickable { dismiss(true) }, which — seeing currentDetent == Hidden — pops immediately.

That is exactly the reported "doesn't show until you interact with the screen".

The fix

Watch the sheet's state instead of the gesture, so every dismissal route is covered rather than just the drag:

  1. wait until the sheet has actually been presented (targetDetent != Hidden — targeted, not settled, so an interrupted open animation still counts);
  2. then wait for it to settle back at Hidden (isIdle && currentDetent == Hidden — a conjunction, because a partial drag flips the target to Hidden and back as the finger crosses the threshold);
  3. pop.

Both explicit dismiss paths (dismiss()'s animate-then-pop and the pendingSheetDismiss replace) now route through the same idempotent finishDismiss(), which the settle observer also calls — so the entry pops exactly once per presentation and can't take a second backstack entry with it. The guard resets on sheetGeneration, so a same-route dismiss-then-replace still re-arms.

Tests

New ModalBottomSheetSceneTest (Robolectric + compose test rule) — the drag case fails on the pre-fix code (expected:<1> but was:<0>) and passes after:

  • dragging the sheet closed pops its entry
  • an open sheet does not pop its entry — control, guards the eager/double-pop direction

Verified:

  • :ui:navigation:testDebugUnitTest — 31 tests, 0 failures (existing CodeNavigator* and InnerFlowNavigator suites included)
  • :apps:flipcash:core:testDebugUnitTest + :apps:flipcash:app:testDebugUnitTest — green

UnstyledBottomSheet has no dismissal callback, so nothing tied "the sheet
settled back at Hidden" to popping its nav entry — that wiring was lost when
the scene moved off Material3's ModalBottomSheet (6e49a91), whose
onDismissRequest did the pop.

A drag-to-dismiss therefore left the (now invisible) sheet entry on the
backstack: currentRouteKey still resolved to the sheet, so chrome that hides
for sheets — the v2 tab bar — stayed hidden, and the full-size alpha-0 scrim
kept swallowing touches until the next tap hit it and popped the entry. Hence
"the tab bar doesn't come back until you interact with the screen" after
dismissing region selection.

Observe the sheet's state rather than the gesture, so every dismissal route is
covered: once the sheet has actually been presented, settling back at Hidden
pops the entry. All paths funnel through an idempotent finishDismiss() that
re-arms per sheetGeneration, so the scrim-tap and pendingSheetDismiss
(dismiss-then-replace) paths can't double-pop while a same-route replace still
works.
@github-actions github-actions Bot added type: fix Bug fix area: ui Compose UI, theme, components, resources labels Aug 20, 2026
@bmc08gt
bmc08gt merged commit 8740136 into code/cash Aug 20, 2026
3 checks passed
@bmc08gt
bmc08gt deleted the claude/sheet-dismiss-tab-bar-4bfc67 branch August 20, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ui Compose UI, theme, components, resources type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant