Skip to content

fix(island): every milestone opens as the reader goes past it - #1155

Open
ExtraToast wants to merge 3 commits into
mainfrom
fix/history-band-skip
Open

fix(island): every milestone opens as the reader goes past it#1155
ExtraToast wants to merge 3 commits into
mainfrom
fix/history-band-skip

Conversation

@ExtraToast

@ExtraToast ExtraToast commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

What

Scrolling the about-us history skipped milestones — one would pass without standing up or telling its story.

Why

HistoryBand watched for crossings of a band across the middle 16% of the screen with an IntersectionObserver. An observer checks once a frame, so a wheel flick that carries a stop clean across that band between two frames reports no crossing at all and the milestone is never told about. The 1.25rem gaps between stops were dead ground for the same reason.

How

The stop being read is measured, not watched: whichever milestone's own middle is nearest the middle of the screen is the one being read, worked out from a scroll listener throttled to one measurement a frame. Distance is always answerable, so there is no scroll speed and no gap at which nothing is being read. Nothing is read while the whole list is above or below the reader, as before.

Tests

HistoryBand.test.ts places the stops by hand (jsdom lays nothing out) and drives real scroll events. New cases: a milestone the page flew past in a single frame still opens, and the middle sitting between two stops still reads one of them.


Diff breakdown added removed, scaled to the largest row.

frontend                                          +591   -207   11
  production         ██████████████████████░░░    +338    -55    7
  unit tests         ████████████████░░░░░░░░░░   +253   -152    4

──────────────────────────────────────────────────────────────────
production                                        +338    -55
tests                                             +253   -152  0.75 test lines per prod line
total (hand-written)                              +591   -207  11 files

Scrolling through the history skipped milestones: one would go by without ever
standing up or telling its story.

The band watched for crossings of the middle 16% of the screen. An observer
checks once a frame, so a wheel flick that carries a stop across that band
between two frames reports no crossing at all, and the milestone is never told
about. The gaps between the stops were dead ground for the same reason.

The stop being read is now measured rather than watched: whichever milestone's
own middle is nearest the middle of the screen is the one being read, worked out
from a scroll listener at most once a frame. Distance is always answerable, so
there is no speed and no gap at which nothing is being read.
The tellings are set in Silkscreen, a bitmap face, and written a character every
other frame with a block cursor at the head of the writing — the pace and the
look of a line of dialogue in a handheld RPG. Each character drops the last
pixel or two into place in two steps as the cursor leaves it behind.

The whole telling holds its room from the start, in no colour, and the cursor
travels across ground the words already occupy. Two reasons. The milestones left
of the line are right-aligned, and text added to while it is right-aligned grows
away from its own end, so the line crawled leftwards and read as though it were
being written backwards. And a telling that claimed its room only once it was
being read pushed everything below it down the page, under a reader who was
scrolling towards it.

The milestones are named the way a quest is, which is the register the rest of
the band now reads in.

Silkscreen is a 226-codepoint face, so what the history is written with is held
to what the file actually carries: the cmap reader the name-coverage test used
moves to tests/unit/styles/glyphCoverage.ts and both tests share it.
Two things on the line had boxes of their own, and a box is a place a line may
break. The cursor was a zero-width inline-block and the character under it an
inline-block of its own, so the paragraph re-wrapped as the cursor travelled
along it: the words jumped up a line and dropped back, over and over.

The cursor is painted out of the flow from an empty inline box, and the
character being written is brought up on opacity alone. Nothing on the line has
a box any more, so the wrap is the wrap of the finished paragraph from the
first character to the last.

The whole line is written now, summary and telling together, and a milestone
nobody has reached shows none of it. A summary drawn beforehand had to be taken
off the page for the writing to start, and text that vanishes to come back is
worse than text that was never there. The room is still held from the start, so
nothing below moves.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant