bugfix: measure bar heights with ResizeObserver instead of magic numbers (0.21.2)
This commit is contained in:
2
backend/Cargo.lock
generated
2
backend/Cargo.lock
generated
@@ -1033,7 +1033,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mangalord"
|
name = "mangalord"
|
||||||
version = "0.21.1"
|
version = "0.21.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argon2",
|
"argon2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mangalord"
|
name = "mangalord"
|
||||||
version = "0.21.1"
|
version = "0.21.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mangalord-frontend",
|
"name": "mangalord-frontend",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -14,11 +14,32 @@
|
|||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
let loggingOut = $state(false);
|
let loggingOut = $state(false);
|
||||||
|
let headerEl: HTMLElement | undefined = $state();
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
theme.init();
|
theme.init();
|
||||||
preferences.init();
|
preferences.init();
|
||||||
if (!session.loaded) session.refresh();
|
if (!session.loaded) session.refresh();
|
||||||
|
|
||||||
|
// Publish the header's measured height as a CSS custom
|
||||||
|
// property so sticky descendants (e.g. the reader nav) can
|
||||||
|
// pin themselves directly below it without guessing. A
|
||||||
|
// ResizeObserver keeps it in sync as the viewport reflows
|
||||||
|
// (the nav `flex-wrap: wrap`s on narrow widths), the user
|
||||||
|
// zooms, or fonts swap. Hard-coded pixel offsets in tokens
|
||||||
|
// are wrong in principle — actual height varies with all
|
||||||
|
// of the above.
|
||||||
|
if (!headerEl) return;
|
||||||
|
const publish = () => {
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
'--app-header-h',
|
||||||
|
`${headerEl!.offsetHeight}px`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
publish();
|
||||||
|
const ro = new ResizeObserver(publish);
|
||||||
|
ro.observe(headerEl);
|
||||||
|
return () => ro.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pull fresh server preferences whenever the user changes (login,
|
// Pull fresh server preferences whenever the user changes (login,
|
||||||
@@ -46,7 +67,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header bind:this={headerEl}>
|
||||||
<nav aria-label="primary">
|
<nav aria-label="primary">
|
||||||
<a class="brand" href="/">Mangalord</a>
|
<a class="brand" href="/">Mangalord</a>
|
||||||
<a class="nav-link" href="/upload">
|
<a class="nav-link" href="/upload">
|
||||||
|
|||||||
@@ -68,6 +68,33 @@
|
|||||||
})();
|
})();
|
||||||
let index = $state(initialIndex);
|
let index = $state(initialIndex);
|
||||||
let continuousPageEls: HTMLImageElement[] = $state([]);
|
let continuousPageEls: HTMLImageElement[] = $state([]);
|
||||||
|
let chapterBarEl: HTMLElement | undefined = $state();
|
||||||
|
|
||||||
|
// Publish the bottom chapter-bar's actual measured height so the
|
||||||
|
// continuous container's `padding-bottom` exactly matches it. Same
|
||||||
|
// rationale as the layout header's measurement: the bar's height
|
||||||
|
// changes with font size, padding, browser zoom, and content
|
||||||
|
// wrap on narrow viewports — a single hard-coded number is wrong.
|
||||||
|
// Only present in continuous mode, so the effect only runs there
|
||||||
|
// and cleans up when the bar unmounts on mode toggle.
|
||||||
|
$effect(() => {
|
||||||
|
if (mode !== 'continuous' || !chapterBarEl) return;
|
||||||
|
const publish = () => {
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
'--reader-bar-h',
|
||||||
|
`${chapterBarEl!.offsetHeight}px`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
publish();
|
||||||
|
const ro = new ResizeObserver(publish);
|
||||||
|
ro.observe(chapterBarEl);
|
||||||
|
return () => {
|
||||||
|
ro.disconnect();
|
||||||
|
// Clear so other pages (single mode, /upload, etc.) don't
|
||||||
|
// inherit a stale reservation.
|
||||||
|
document.documentElement.style.removeProperty('--reader-bar-h');
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// ---- Navigation ----
|
// ---- Navigation ----
|
||||||
//
|
//
|
||||||
@@ -538,7 +565,11 @@
|
|||||||
|
|
||||||
<!-- Sticky bottom bar — always visible at the foot of the viewport
|
<!-- Sticky bottom bar — always visible at the foot of the viewport
|
||||||
in continuous mode. Slides off when full-screen is toggled. -->
|
in continuous mode. Slides off when full-screen is toggled. -->
|
||||||
<div class="chapter-bar" data-testid="chevrons-inline-bottom">
|
<div
|
||||||
|
class="chapter-bar"
|
||||||
|
bind:this={chapterBarEl}
|
||||||
|
data-testid="chevrons-inline-bottom"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-btn"
|
class="inline-btn"
|
||||||
|
|||||||
Reference in New Issue
Block a user