Skip to content

Commit 014ab60

Browse files
committed
Improved back-to-top button behavior on anchor jump
1 parent 0a08e67 commit 014ab60

File tree

7 files changed

+57
-54
lines changed

7 files changed

+57
-54
lines changed

material/assets/javascripts/bundle.01de222e.min.js

+29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

material/assets/javascripts/bundle.01de222e.min.js.map

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

material/assets/javascripts/bundle.1514a9a0.min.js

-29
This file was deleted.

material/assets/javascripts/bundle.1514a9a0.min.js.map

-8
This file was deleted.

material/base.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@
213213
</script>
214214
{% endblock %}
215215
{% block scripts %}
216-
<script src="{{ 'assets/javascripts/bundle.1514a9a0.min.js' | url }}"></script>
216+
<script src="{{ 'assets/javascripts/bundle.01de222e.min.js' | url }}"></script>
217217
{% for path in config["extra_javascript"] %}
218218
<script src="{{ path | url }}"></script>
219219
{% endfor %}

src/assets/javascripts/bundle.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ const content$ = defer(() => merge(
233233

234234
/* Back-to-top button */
235235
...getComponentElements("top")
236-
.map(el => mountBackToTop(el, { viewport$, header$, main$ }))
236+
.map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))
237237
))
238238

239239
/* Set up component observables */

src/assets/javascripts/components/top/index.ts

+18-15
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
endWith,
3131
finalize,
3232
map,
33+
repeat,
34+
skip,
3335
takeLast,
3436
takeUntil,
3537
tap
@@ -61,8 +63,8 @@ export interface BackToTop {
6163
*/
6264
interface WatchOptions {
6365
viewport$: Observable<Viewport> /* Viewport observable */
64-
header$: Observable<Header> /* Header observable */
6566
main$: Observable<Main> /* Main area observable */
67+
target$: Observable<HTMLElement> /* Location target observable */
6668
}
6769

6870
/**
@@ -72,6 +74,7 @@ interface MountOptions {
7274
viewport$: Observable<Viewport> /* Viewport observable */
7375
header$: Observable<Header> /* Header observable */
7476
main$: Observable<Main> /* Main area observable */
77+
target$: Observable<HTMLElement> /* Location target observable */
7578
}
7679

7780
/* ----------------------------------------------------------------------------
@@ -87,33 +90,33 @@ interface MountOptions {
8790
* @returns Back-to-top observable
8891
*/
8992
export function watchBackToTop(
90-
_el: HTMLElement, { viewport$, main$ }: WatchOptions
93+
_el: HTMLElement, { viewport$, main$, target$ }: WatchOptions
9194
): Observable<BackToTop> {
9295

9396
/* Compute direction */
9497
const direction$ = viewport$
9598
.pipe(
9699
map(({ offset: { y } }) => y),
97100
bufferCount(2, 1),
98-
map(([a, b]) => a > b && b),
101+
map(([a, b]) => a > b),
99102
distinctUntilChanged()
100103
)
101104

102-
/* Compute whether button should be hidden */
103-
const hidden$ = main$
105+
/* Compute whether main area is active */
106+
const active$ = main$
104107
.pipe(
105-
distinctUntilKeyChanged("active")
108+
map(({ active }) => active)
106109
)
107110

108111
/* Compute threshold for hiding */
109-
return combineLatest([hidden$, direction$])
112+
return combineLatest([active$, direction$])
110113
.pipe(
111-
map(([{ active }, direction]) => ({
112-
hidden: !(active && direction)
113-
})),
114-
distinctUntilChanged((a, b) => (
115-
a.hidden === b.hidden
116-
))
114+
map(([active, direction]) => !(active && direction)),
115+
distinctUntilChanged(),
116+
takeUntil(target$.pipe(skip(1))),
117+
endWith(true),
118+
repeat({ delay: 250 }),
119+
map(hidden => ({ hidden }))
117120
)
118121
}
119122

@@ -128,7 +131,7 @@ export function watchBackToTop(
128131
* @returns Back-to-top component observable
129132
*/
130133
export function mountBackToTop(
131-
el: HTMLElement, { viewport$, header$, main$ }: MountOptions
134+
el: HTMLElement, { viewport$, header$, main$, target$ }: MountOptions
132135
): Observable<Component<BackToTop>> {
133136
const push$ = new Subject<BackToTop>()
134137
push$.subscribe({
@@ -164,7 +167,7 @@ export function mountBackToTop(
164167
})
165168

166169
/* Create and return component */
167-
return watchBackToTop(el, { viewport$, header$, main$ })
170+
return watchBackToTop(el, { viewport$, main$, target$ })
168171
.pipe(
169172
tap(state => push$.next(state)),
170173
finalize(() => push$.complete()),

0 commit comments

Comments
 (0)