Skip to content

Commit ec9e2a3

Browse files
committed
Fixed scroll offset when activating linked content tabs
1 parent e7a8ae0 commit ec9e2a3

File tree

7 files changed

+71
-35
lines changed

7 files changed

+71
-35
lines changed

material/assets/javascripts/bundle.48f2be22.min.js.map

-8
This file was deleted.

material/assets/javascripts/bundle.48f2be22.min.js renamed to material/assets/javascripts/bundle.d691e9de.min.js

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

material/assets/javascripts/bundle.d691e9de.min.js.map

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

material/base.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@
245245
</script>
246246
{% endblock %}
247247
{% block scripts %}
248-
<script src="{{ 'assets/javascripts/bundle.48f2be22.min.js' | url }}"></script>
248+
<script src="{{ 'assets/javascripts/bundle.d691e9de.min.js' | url }}"></script>
249249
{% for path in config.extra_javascript %}
250250
<script src="{{ path | url }}"></script>
251251
{% endfor %}

src/assets/javascripts/bundle.ts

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

214214
/* Content */
215215
...getComponentElements("content")
216-
.map(el => mountContent(el, { target$, print$ })),
216+
.map(el => mountContent(el, { viewport$, target$, print$ })),
217217

218218
/* Search highlighting */
219219
...getComponentElements("content")

src/assets/javascripts/components/content/_/index.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import { Observable, merge } from "rxjs"
2424

25-
import { getElements } from "~/browser"
25+
import { Viewport, getElements } from "~/browser"
2626

2727
import { Component } from "../../_"
2828
import { Annotation } from "../annotation"
@@ -68,6 +68,7 @@ export type Content =
6868
* Mount options
6969
*/
7070
interface MountOptions {
71+
viewport$: Observable<Viewport> /* Viewport observable */
7172
target$: Observable<HTMLElement> /* Location target observable */
7273
print$: Observable<boolean> /* Media print observable */
7374
}
@@ -88,7 +89,7 @@ interface MountOptions {
8889
* @returns Content component observable
8990
*/
9091
export function mountContent(
91-
el: HTMLElement, { target$, print$ }: MountOptions
92+
el: HTMLElement, { viewport$, target$, print$ }: MountOptions
9293
): Observable<Component<Content>> {
9394
return merge(
9495

@@ -110,6 +111,6 @@ export function mountContent(
110111

111112
/* Content tabs */
112113
...getElements("[data-tabs]", el)
113-
.map(child => mountContentTabs(child))
114+
.map(child => mountContentTabs(child, { viewport$ }))
114115
)
115116
}

src/assets/javascripts/components/content/tabs/index.ts

+51-16
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ import {
3737
subscribeOn,
3838
takeLast,
3939
takeUntil,
40-
tap
40+
tap,
41+
withLatestFrom
4142
} from "rxjs"
4243

4344
import { feature } from "~/_"
4445
import {
46+
Viewport,
4547
getElement,
4648
getElementContentOffset,
4749
getElementContentSize,
@@ -66,6 +68,17 @@ export interface ContentTabs {
6668
active: HTMLLabelElement /* Active tab label */
6769
}
6870

71+
/* ----------------------------------------------------------------------------
72+
* Helper types
73+
* ------------------------------------------------------------------------- */
74+
75+
/**
76+
* Mount options
77+
*/
78+
interface MountOptions {
79+
viewport$: Observable<Viewport> /* Viewport observable */
80+
}
81+
6982
/* ----------------------------------------------------------------------------
7083
* Functions
7184
* ------------------------------------------------------------------------- */
@@ -102,11 +115,12 @@ export function watchContentTabs(
102115
* this functionality ourselves.
103116
*
104117
* @param el - Content tabs element
118+
* @param options - Options
105119
*
106120
* @returns Content tabs component observable
107121
*/
108122
export function mountContentTabs(
109-
el: HTMLElement
123+
el: HTMLElement, { viewport$ }: MountOptions
110124
): Observable<Component<ContentTabs>> {
111125

112126
/* Render content tab previous button for pagination */
@@ -189,23 +203,44 @@ export function mountContentTabs(
189203

190204
/* Set up linking of content tabs, if enabled */
191205
if (feature("content.tabs.link"))
192-
push$.pipe(skip(1))
193-
.subscribe(({ active }) => {
206+
push$.pipe(
207+
skip(1),
208+
withLatestFrom(viewport$)
209+
)
210+
.subscribe(([{ active }, { offset }]) => {
194211
const tab = active.innerText.trim()
195-
for (const set of getElements("[data-tabs]"))
196-
for (const input of getElements<HTMLInputElement>(
197-
":scope > input", set
198-
)) {
199-
const label = getElement(`label[for="${input.id}"]`)
200-
if (label.innerText.trim() === tab) {
201-
input.click()
202-
break
212+
if (active.hasAttribute("data-md-switching")) {
213+
active.removeAttribute("data-md-switching")
214+
215+
/* Determine viewport offset of active tab */
216+
} else {
217+
const y = el.offsetTop - offset.y
218+
219+
/* Passively activate other tabs */
220+
for (const set of getElements("[data-tabs]"))
221+
for (const input of getElements<HTMLInputElement>(
222+
":scope > input", set
223+
)) {
224+
const label = getElement(`label[for="${input.id}"]`)
225+
if (
226+
label !== active &&
227+
label.innerText.trim() === tab
228+
) {
229+
label.setAttribute("data-md-switching", "")
230+
input.click()
231+
break
232+
}
203233
}
204-
}
205234

206-
/* Persist active tabs in local storage */
207-
const tabs = __md_get<string[]>("__tabs") || []
208-
__md_set("__tabs", [...new Set([tab, ...tabs])])
235+
/* Bring active tab into view */
236+
window.scrollTo({
237+
top: el.offsetTop - y
238+
})
239+
240+
/* Persist active tabs in local storage */
241+
const tabs = __md_get<string[]>("__tabs") || []
242+
__md_set("__tabs", [...new Set([tab, ...tabs])])
243+
}
209244
})
210245

211246
/* Create and return component */

0 commit comments

Comments
 (0)