Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-use-history-api-for-hash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wethegit/react-modal": minor
---

Use the History API (`pushState`/`replaceState`) instead of directly assigning `window.location.hash` when opening and closing hash-linked modals. This prevents Safari from scrolling the user to the top of the page. Also adds a `popstate` listener so browser back/forward navigation correctly opens and closes the modal.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions src/lib/hooks/use-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function useModal(props: UseModalOptions = {}) {
// an extra dependecy and stay within the render loop
current = cur

if (cur !== ModalStates.CLOSED) return ModalStates.CLOSED
if (cur !== ModalStates.CLOSED) return ModalStates.CLOSED
return cur
})

Expand All @@ -37,7 +37,6 @@ export function useModal(props: UseModalOptions = {}) {
if (current === ModalStates.CLOSED || !current) return

if (hash && window && window.location.hash === `#${hash}`) {
window.location.hash = ""
window.history.replaceState({}, "", window.location.pathname)
Comment thread
marlonmarcello marked this conversation as resolved.
Resolved
}
Comment thread
marlonmarcello marked this conversation as resolved.
Resolved

Expand All @@ -59,7 +58,7 @@ export function useModal(props: UseModalOptions = {}) {
if (current === ModalStates.OPEN) return

if (hash && window && window.location.hash !== `#${hash}`) {
window.location.hash = `#${hash}`
window.history.pushState({}, "", `#${hash}`)
}
Comment thread
marlonmarcello marked this conversation as resolved.
Resolved
}, [hash])

Expand All @@ -81,10 +80,15 @@ export function useModal(props: UseModalOptions = {}) {
// Check for a hash on mount
handleHashChange()

// hashchange fires when navigating to same-page anchors (e.g. <a href="#hash">)
window.addEventListener("hashchange", handleHashChange)
// popstate fires when navigating via browser history (back/forward),
// which is what history.pushState entries use
window.addEventListener("popstate", handleHashChange)

return () => {
window.removeEventListener("hashchange", handleHashChange)
window.removeEventListener("popstate", handleHashChange)
}
}, [handleClose, handleOpen, hash])

Expand Down
Loading