@@ -101,6 +101,7 @@ function useScrollLock(
101
101
if ( ! ownerDocument ) return
102
102
103
103
let d = disposables ( )
104
+ let scrollPosition = window . pageYOffset
104
105
105
106
function style ( node : HTMLElement , property : string , value : string ) {
106
107
let previous = node . style . getPropertyValue ( property )
@@ -123,10 +124,36 @@ function useScrollLock(
123
124
}
124
125
125
126
if ( isIOS ( ) ) {
126
- let scrollPosition = window . pageYOffset
127
- style ( document . body , 'marginTop' , `-${ scrollPosition } px` )
127
+ style ( ownerDocument . body , 'marginTop' , `-${ scrollPosition } px` )
128
128
window . scrollTo ( 0 , 0 )
129
129
130
+ // Relatively hacky, but if you click a link like `<a href="#foo">` in the Dialog, and there
131
+ // exists an element on the page (outside of the Dialog) with that id, then the browser will
132
+ // scroll to that position. However, this is not the case if the element we want to scroll to
133
+ // is higher and the browser needs to scroll up, but it doesn't do that.
134
+ //
135
+ // Let's try and capture that element and store it, so that we can later scroll to it once the
136
+ // Dialog closes.
137
+ let scrollToElement : HTMLElement | null = null
138
+ d . addEventListener (
139
+ ownerDocument ,
140
+ 'click' ,
141
+ ( e ) => {
142
+ if ( e . target instanceof HTMLElement ) {
143
+ try {
144
+ let anchor = e . target . closest ( 'a' )
145
+ if ( ! anchor ) return
146
+ let { hash } = new URL ( anchor . href )
147
+ let el = ownerDocument . querySelector ( hash )
148
+ if ( el && ! resolveAllowedContainers ( ) . some ( ( container ) => container . contains ( el ) ) ) {
149
+ scrollToElement = el as HTMLElement
150
+ }
151
+ } catch ( err ) { }
152
+ }
153
+ } ,
154
+ true
155
+ )
156
+
130
157
d . addEventListener (
131
158
ownerDocument ,
132
159
'touchmove' ,
@@ -161,6 +188,13 @@ function useScrollLock(
161
188
// (Since the value of window.pageYOffset is 0 in the first case, we should be able to
162
189
// always sum these values)
163
190
window . scrollTo ( 0 , window . pageYOffset + scrollPosition )
191
+
192
+ // If we captured an element that should be scrolled to, then we can try to do that if the
193
+ // element is still connected (aka, still in the DOM).
194
+ if ( scrollToElement && scrollToElement . isConnected ) {
195
+ scrollToElement . scrollIntoView ( { block : 'nearest' } )
196
+ scrollToElement = null
197
+ }
164
198
} )
165
199
}
166
200
0 commit comments