diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 66cda5e..734a320 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1033,7 +1033,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "mangalord" -version = "0.20.0" +version = "0.21.0" dependencies = [ "anyhow", "argon2", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index a6c73b8..46884cd 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mangalord" -version = "0.20.0" +version = "0.21.0" edition = "2021" [lib] diff --git a/frontend/package.json b/frontend/package.json index b2193f6..d4417b4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mangalord-frontend", - "version": "0.20.0", + "version": "0.21.0", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/lib/reader-fullscreen.svelte.ts b/frontend/src/lib/reader-fullscreen.svelte.ts new file mode 100644 index 0000000..5885c5f --- /dev/null +++ b/frontend/src/lib/reader-fullscreen.svelte.ts @@ -0,0 +1,33 @@ +/** + * Cross-component flag for the reader's "hide all chrome" view. + * + * The reader page toggles this; the root layout reads it to hide the + * top app navbar; the reader itself reads it to hide its own nav bar + * and bottom chapter bar. CSS handles the slide animations via a + * `data-reader-fullscreen` attribute on `` so the entire frame + * (layout chrome included) stays synchronised. + * + * Always reset on reader unmount — letting the flag leak across + * navigation would orphan a hidden app navbar on other pages. + */ +let active = $state(false); + +export const readerFullscreen = { + get value() { + return active; + }, + set value(v: boolean) { + active = v; + if (typeof document !== 'undefined') { + if (v) document.documentElement.dataset.readerFullscreen = 'true'; + else delete document.documentElement.dataset.readerFullscreen; + } + }, + toggle() { + this.value = !active; + }, + /** Force off — call from the reader's onDestroy. */ + reset() { + this.value = false; + } +}; diff --git a/frontend/src/lib/styles/tokens.css b/frontend/src/lib/styles/tokens.css index 41f1819..2408b45 100644 --- a/frontend/src/lib/styles/tokens.css +++ b/frontend/src/lib/styles/tokens.css @@ -60,6 +60,13 @@ --icon-md: 18px; --icon-lg: 22px; + /* App-frame heights (fixed-position bars at the top and bottom of + the viewport). Used by the layout + reader to reserve content + space and animate fullscreen mode. Recomputed once if the + header padding/font-size ever changes — keep in sync. */ + --app-header-h: 60px; + --reader-bar-h: 56px; + --z-dropdown: 10; --z-sticky: 50; --z-modal: 100; diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 06966a8..296441a 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -149,6 +149,24 @@ font-size: var(--font-sm); } + /* App frame: header is fixed at the viewport top with a slide + transition so reader fullscreen (set via `data-reader-fullscreen` + on ``) can hide it without jolting the layout. `main` pays + the gap with a matching padding-top that animates in lockstep. */ + header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: var(--z-sticky); + transform: translateY(0); + transition: transform 220ms ease-out; + } + + :global(html[data-reader-fullscreen='true']) header { + transform: translateY(-100%); + } + .session { display: flex; align-items: center; @@ -186,7 +204,17 @@ main { padding: var(--space-4); + /* Reserve room for the fixed header so its presence doesn't + overlap content. The min-height is a fallback that matches + the header at typical viewport sizes (60–72px); resize + observers would be more accurate but the gap is forgiving. */ + padding-top: calc(var(--app-header-h) + var(--space-4)); max-width: 64rem; margin: 0 auto; + transition: padding-top 220ms ease-out; + } + + :global(html[data-reader-fullscreen='true']) main { + padding-top: var(--space-4); } diff --git a/frontend/src/routes/manga/[id]/chapter/[n]/+page.svelte b/frontend/src/routes/manga/[id]/chapter/[n]/+page.svelte index 42a9c18..bde11f0 100644 --- a/frontend/src/routes/manga/[id]/chapter/[n]/+page.svelte +++ b/frontend/src/routes/manga/[id]/chapter/[n]/+page.svelte @@ -1,9 +1,11 @@