Skip to content

Keep the home hero rotating, with a pause control - #25

Merged
rdlu merged 3 commits into
mainfrom
feat/hero-rotate
Oct 17, 2026
Merged

rdlu merged 3 commits into
mainfrom
feat/hero-rotate

Conversation

@rdlu

@rdlu rdlu commented Oct 17, 2026

Copy link
Copy Markdown
Owner

The home hero from #11 no longer stops on the tagline. It types each line, holds it, backspaces it and moves on to the next, round and round, with the same 35-70 ms jitter as before.

Phrases

All lines are in one array in site/src/views/Home.svelte, written as { text, hold }. Adding, dropping or retiming a line changes one line of code.

# Line Hold
1 NMSii: No Man's Sky Items Interface 4.5 s
2 The numbers No Man's Sky doesn't show you 5 s (the real tagline)
3 16 glyphs. 0 wiki tabs. 2.5 s
4 Six-teen. Not six-seven. :x 2.5 s

Line 4 is the 6-7 meme. It is a separate entry with a comment, so it can be dropped when the meme ages. :x is plain ASCII, so it renders in 0xProto and doesn't affect line height.

Other 16 jokes that could replace line 3:

  • 12 glyphs to anywhere. 16 to choose from.
  • Portal addresses: 12 glyphs, 16 to pick from, 0 guesswork.
  • 16 glyphs, 16 Atlas interfaces, 1 spreadsheet.
  • The Atlas counts in 16. So do we.

Behaviour

  • Return visits: the intro that opens with the NMSii name plays once per page load. If you come back to Home in the same load, the rotation starts at the tagline, already typed.
  • Cursor: solid while it types or erases, and blinking while a line is held or paused.
  • No layout shift: every line sits invisibly in the h1's grid cell, so the box always has the height of the tallest line at the current width.

Pausing (WCAG 2.2.2)

I added a small ‖ pause / ▶ resume toggle instead of making the h1 clickable. Making the heading a button would remove its heading semantics. An h1 that toggles on click also gives no hint that it can be clicked.

  • The toggle sits in the h1's bottom margin and is positioned absolutely, so it takes no space and can't shift anything.
  • It is a 24 px target, with an aria-label that switches between "Pause the title animation" and "Resume the title animation".
  • It uses the site's usual focus ring.

The rotation also stops in these cases:

  • the mouse is over the line (mouse only, so a tap doesn't leave it stuck)
  • the toggle has keyboard focus (:focus-visible); pressing it to resume also lifts this hold
  • the tab is hidden (visibilitychange)
  • the hero is scrolled out of view (IntersectionObserver)

A pause keeps the current position in the line. Every timer and observer is cleared when the page is destroyed.

Screen readers only hear the h1's aria-label, which is the tagline, and never the rotation. With reduced motion the tagline is shown still, with no toggle and no rotation.

Also: Enter on focused links and buttons

The page-wide key handler (lib/keys.js) treated Enter as the view's pivot key and called preventDefault. As a result, Enter could not activate a focused link or button anywhere on the site, and the new toggle didn't respond to Enter either. Enter on a[href], button and summary now does the browser's default. The pivot still works when focus is on the page or a list. This is a separate commit.

<title>, the markdown export and llms.txt are unchanged.

Checks

  • npm run check: 0 errors, 0 warnings
  • mise run test: 247 passed
  • Headless chromium against dist/ (CDP), dark and light themes, at 1400 px and 390 px:
    • Height: the h1 was sampled every 50 ms for 28 s (about 530 samples per run), covering a full cycle with all four lines seen. Its height never changed: 117.75 px at 1400 px and 104.86 px at 390 px. The lede's top didn't move either.
    • Pausing: hovering, a hidden tab (document.hidden overridden and visibilitychange dispatched) and scrolling the hero away each kept the text unchanged for 5.5 s mid-typing, and it resumed afterwards.
    • Toggle: keyboard focus on it holds the rotation, Enter pauses, and Enter again resumes.
    • Reduced motion: the tagline is static, at the same height, with no toggle.
  • mise run web:lighthouse --local --preset desktop: perf 97, a11y 100, CLS 0.006

🤖 Generated with Claude Code

rdlu and others added 2 commits October 17, 2026 12:40
The page-wide key handler took Enter for the view's pivot and called
preventDefault, so a keyboard user could not follow a focused link or press
a focused button anywhere on the site. Enter on those is the browser's now;
the pivot still runs when focus is on the page or a list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The typed tagline was liked enough to keep going: the hero now cycles the
name, the tagline and two jokes on 16, each held for its own time (the name
and tagline longer). All lines sit invisibly in the hero's grid cell, so its
height is the tallest line's and the page never shifts.

Motion that runs past 5 s needs a way to stop it (WCAG 2.2.2), so a small
"pause" toggle hangs in the h1's bottom margin, out of the flow; hovering the
line or keyboard focus on the toggle holds it too. A hidden tab or a hero
scrolled out of view stops the timers. Screen readers still get only the
tagline, and reduced motion gets it still, with no toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rdlu rdlu added enhancement New feature or request area: web The website: Svelte, PWA, markdown export labels Oct 17, 2026
The user's pick from the alternatives: it lands the 16 on the game's
own lore rather than on portal arithmetic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rdlu
rdlu merged commit 76b716a into main Oct 17, 2026
1 check passed
@rdlu
rdlu deleted the feat/hero-rotate branch October 17, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: web The website: Svelte, PWA, markdown export enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant