Fixed replacement of skip link and announcement bar on instant load

This commit is contained in:
squidfunk
2020-03-28 18:10:08 +01:00
parent edc9d6fc61
commit 908d34b853
14 changed files with 93 additions and 58 deletions

View File

@@ -39,6 +39,7 @@ import { getElement, replaceElement } from "browser"
* Component
*/
export type Component =
| "announce" /* Announcement bar */
| "container" /* Container */
| "header" /* Header */
| "header-title" /* Header title */
@@ -114,6 +115,7 @@ export function setupComponents(
switch (name) {
/* Top-level components: update */
case "announce":
case "header-title":
case "container":
case "skip":

View File

@@ -73,6 +73,7 @@ export interface Header {
* Mount options
*/
interface MountOptions {
document$: Observable<Document> /* Document observable */
viewport$: Observable<Viewport> /* Viewport observable */
}
@@ -88,11 +89,11 @@ interface MountOptions {
* @return Operator function
*/
export function mountHeader(
{ viewport$ }: MountOptions
{ document$, viewport$ }: MountOptions
): OperatorFunction<HTMLElement, Header> {
return pipe(
switchMap(el => {
const header$ = watchHeader(el)
const header$ = watchHeader(el, { document$ })
/* Compute whether the header should switch to page header */
const type$ = useComponent("main")

View File

@@ -28,10 +28,12 @@ import {
pipe
} from "rxjs"
import {
distinctUntilChanged,
finalize,
map,
observeOn,
shareReplay,
switchMap,
tap
} from "rxjs/operators"
@@ -43,6 +45,17 @@ import {
setHeaderTitleActive
} from "../set"
/* ----------------------------------------------------------------------------
* Helper types
* ------------------------------------------------------------------------- */
/**
* Watch options
*/
interface WatchOptions {
document$: Observable<Document> /* Document observable */
}
/* ----------------------------------------------------------------------------
* Functions
* ------------------------------------------------------------------------- */
@@ -55,27 +68,36 @@ import {
* @return Header observable
*/
export function watchHeader(
el: HTMLElement
el: HTMLElement, { document$ }: WatchOptions
): Observable<Omit<Header, "type">> {
const styles = getComputedStyle(el)
if ([
"sticky", /* Modern browsers */
"-webkit-sticky" /* Safari */
].includes(styles.position)) {
return watchElementSize(el)
.pipe(
map(({ height }) => ({
sticky: true,
height
})),
shareReplay(1)
)
} else {
return of({
sticky: false,
height: 0
})
}
return document$
.pipe(
map(() => {
const styles = getComputedStyle(el)
return [
"sticky", /* Modern browsers */
"-webkit-sticky" /* Safari */
].includes(styles.position)
}),
distinctUntilChanged(),
switchMap(sticky => {
if (sticky) {
return watchElementSize(el)
.pipe(
map(({ height }) => ({
sticky: true,
height
}))
)
} else {
return of({
sticky: false,
height: 0
})
}
}),
shareReplay(1)
)
}
/* ------------------------------------------------------------------------- */