fix: make the reader's typography, width and arrow keys work

Typography was in the stylesheet foliate prepends, which the book overrides;
moved to the appended one. The window keydown handler was never bound.

Also: wider reading area, page on a card, arrows moved onto it, spread gutter,
and the sidebar stays open on chapter clicks.
This commit is contained in:
2026-08-11 22:45:14 -04:00
parent 6318115380
commit 9155129ccd
5 changed files with 135 additions and 62 deletions
@@ -48,6 +48,20 @@
// Reactive so the effects below re-run once the book is open — otherwise a
// theme flip while it was still loading would never reach the book.
let ready = $state(false);
let hostWidth = $state(0);
/**
* How many columns the paginator will actually lay out.
*
* It decides this internally and exposes it only as a custom property inside
* its shadow root, so the formula is mirrored here to place the spread
* divider. Kept in step with paginator.js's `divisor`.
*/
const columns = $derived(
settings.flow === 'scrolled' || hostWidth === 0
? 1
: Math.min(settings.maxColumnCount, Math.ceil(hostWidth / settings.maxInlineSize))
);
/**
* Where to resume from.
@@ -130,6 +144,11 @@
onMount(() => {
let disposed = false;
const resizeObserver = new ResizeObserver(([entry]) => {
hostWidth = entry.contentRect.width;
});
if (container) resizeObserver.observe(container);
(async () => {
try {
await loadFoliate();
@@ -180,6 +199,7 @@
return () => {
disposed = true;
resizeObserver.disconnect();
for (const { doc } of view?.renderer?.getContents?.() ?? []) {
doc.removeEventListener('keydown', onKeydown);
}
@@ -211,9 +231,25 @@
});
</script>
<svelte:window {onkeydown} />
<!--
Not {onkeydown}: that shorthand resolves to the global window.onkeydown
property, which TypeScript accepts and which is null at runtime, so the
handler silently never ran and arrows only worked once the book had focus.
-->
<svelte:window onkeydown={onKeydown} />
<div bind:this={container} class="foliate-host"></div>
<div class="relative h-full w-full">
<div bind:this={container} class="foliate-host"></div>
{#if ready && columns === 2}
<!-- The gutter between the two pages of a spread. Sits in the column gap,
so it never crosses text. -->
<div
aria-hidden="true"
class="pointer-events-none absolute inset-y-[6%] left-1/2 w-px -translate-x-1/2 bg-border"
></div>
{/if}
</div>
<style>
/* foliate-view extends bare HTMLElement, so it has no default display. */