feat(dialog): the browser Forward reopens what Back closed - #39
Open
ivanbanov wants to merge 1 commit into
Open
Conversation
closeOnBack becomes symmetric. The guard entry a Back press pops survives in the forward stack, still marking the dialog's open ground: a traversal re-entering it is the host's Forward and reopens the dialog, guarded again for the next Back. One setting gates both directions. - dom-navigation: interceptBackNavigation(onBack, onForward?) — a Back-closed guard parks instead of dropping; a landing on its spent entry offers the reopen and re-arms the guard on the entry in place. Ownership of the landing entry, not traversal direction, decides reopen vs unwind: marked ground with no armed owner is forward residue and never unwinds a layer. - dialog (core): history.forward mirrors history.back, gated by the same closeOnBack, reachable from closed and from the animated closing state (Forward interrupts the exit); forwardNavigate() on the api with a new onForwardNavigation veto callback, per the shared dismissal contract. - react-dialog: one registration spans the whole episode — armed while open, parked through a Back-close, released on any other close or on unmount. Reopening through the trigger plants a fresh entry, truncating the spent one, exactly like navigating after a Back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
closeOnBackbecomes symmetric: the browser's Back closes the dialog (as before), and the browser's Forward now reopens what Back closed — guarded again for the next Back. No new setting: back-close and forward-reopen are one behavior (the dialog's openness tracking the history position), so the existingcloseOnBackgates both.The reopen follows the shared dismissal contract: a new
onForwardNavigationcallback fires first andpreventDefault()vetoes; a controlled dialog only records the intent.How
The model that keeps this cheap: the guard entry a Back press pops isn't gone — it survives in the browser's forward stack, still marking the dialog's open ground. A traversal re-entering it is the host's Forward.
@dunky.dev/dom-navigation—interceptBackNavigation(onBack, onForward?)grew the optional second callback. A Back-closed guard parks instead of dropping; apopstatelanding on its spent entry offers the reopen and re-arms the guard on the entry in place (no new entry planted). The safety invariant: parked entries always sit above every armed entry (every planted entry truncates the forward stack), so ownership of the landing entry — not traversal direction, whichpopstatedoesn't carry — decides reopen vs unwind. Marked ground with no armed owner never unwinds a layer; without that, Forward onto a dead nested-dialog entry would wrongly close its parent. Callers that don't passonForwardbehave exactly as before.@dunky.dev/dialog—history.forwardmirrorshistory.back, gated by the samecloseOnBack, reachable fromclosedand from the animatedclosingstate (Forward interrupts the exit). The connect gainsforwardNavigate(), sharing the synthesized veto payload withbackNavigate().@dunky.dev/react-dialog— one registration spans the whole episode: armed while open, parked through a Back-close (releasing there would end the Forward watch), released on any other close or on unmount. Reopening through the trigger plants a fresh entry, truncating the spent one — exactly like navigating after a Back.Caveats (spec'd)
onForward); noted next to the react story. Mirroring it is a small follow-up once feat(vue): the Vue substrate, opening with Dialog #38 lands.Testing
closeOnBackstory gained a "Simulate browser Forward" button.🤖 Generated with Claude Code