Skip to content

site: make every interactive part an explicit state machine - #4

Merged
grimgrimberg merged 1 commit into
devfrom
claude/explicit-state-machines
Nov 8, 2026
Merged

grimgrimberg merged 1 commit into
devfrom
claude/explicit-state-machines

Conversation

@grimgrimberg

Copy link
Copy Markdown
Owner

The site's interactive parts kept their state spread across booleans, timers, CSS classes and DOM nodes. That caused real bugs: one Escape closed every open layer at once, a stale Clippy popped back over the goose, "Copied Email" stuck on the button after a double click, and a lab's status said "running" after it had paused. It was also hard for people, tests and agents to tell what state anything was in.

Every interactive part is now an explicit state machine. A small helper, assets/js/state-machine.js, gives each part one named state and a fixed set of allowed transitions. That state is mirrored onto <html> as data-<name>-state, and PortfolioState.snapshot() returns all of them at once. docs/site/STATE.md lists all 18 machines and the rules for adding one.

What visitors get

  • Escape: it closes only the top layer, and only that layer traps Tab focus. The drawer, palette, dialogs and goose join one overlay stack.
  • Mobile drawer: a nav link leaves focus on the section it jumped to. Widening the window closes the drawer, so the overlay and scroll lock no longer stay behind.
  • Clippy: a delayed guide can no longer reappear over something newer. A failed load can be retried. Stopping the goose no longer hides Clippy for the whole visit, and its messages are announced to screen readers.
  • Labs:
    • The reconstruction viewer really unloads when you scroll away.
    • A late page load no longer snaps you back to the lab named in the URL.
    • Focus survives the viewer closing itself.
    • Each lab's code loads and fails on its own, so one failure no longer marks both labs as broken.
  • Simulations: every pause, including automatic ones, updates the status text and readout. A WebGL failure is not retried on every scroll.
  • Brain viewer: it stops rendering when off screen and handles WebGL context loss.
  • Contact: double-clicking copy no longer gets stuck. "Build another draft" returns to the form with what you typed.
  • Smaller fixes: role tabs are linked to their panel for screen readers, the Konami code resets properly, and the goose returns focus when it leaves.

For reviewers

  • photo-page.js is intentionally untouched, because photo-page changes need the owner's approval first. photo.html only gains the shared script tag.
  • state-machine.js loads before site-shell.js on the homepage, the photo page and the Fly101 page.
  • There is a new smoke test, "interactive state is explicit…". It covers the overlay stack, the double-click copy, the draft round trip, the drawer's states and focus, and the snapshot.
  • Locally, static lint, the model tests, hygiene (6 passed) and smoke (15 passed) all pass. They ran on local Chromium 1248, not the pinned build.

🤖 Generated with Claude Code

Created with Claude Opus 5.5 in Claude Code.

Interactive state was spread across booleans, timers, classes and DOM nodes,
which caused races and stale UI. A small helper (assets/js/state-machine.js)
gives each part one named state with guarded transitions, mirrored onto
<html data-<name>-state> and listed by PortfolioState.snapshot().

- Overlay stack: Escape closes only the top overlay, one focus trap at a time
- Fix confirmed bugs in the drawer, Clippy, labs, sims, copy and contact flows
- docs/site/STATE.md documents every machine; new smoke test covers the fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 8, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-08T21:09:36.570008Z 1a2fde4 PR opened
🔒 Security Review ✅ Completed 2026-11-08T21:10:28.571899Z 1a2fde4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@grimgrimberg
grimgrimberg merged commit 7e96b2c into dev Nov 8, 2026
1 check passed
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.

3 participants