Skip to content

Jump from a reply to the boards it made or changed, and a theme switch - #197

Merged
Jing-yilin merged 6 commits into
mainfrom
jump-to
Oct 8, 2026
Merged

Jing-yilin merged 6 commits into
mainfrom
jump-to

Conversation

@Jing-yilin

@Jing-yilin Jing-yilin commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Under each agent reply in the chat, a button for every board the run made or rewrote. Clicking one brings its canvas forward and fits the board to the view, as a double-click does. The dot is blue for a new board and green for a rewritten one, the colours of their rings on the canvas. More than three rows of buttons fold behind "Show all N".

This PR also carries the theme switch (system, light or dark) from theme-toggle, merged in as a dependency. It was never opened as a PR of its own.

  • Server (agent.ts): hashes the project's boards when a run starts and again as its end event is written, and adds made: [{board, status}] to that event. It works off the files rather than the tool lines, so a board a generator (gen.py) wrote counts, and one it wrote again with the same bytes doesn't.
  • boards.ts: hashBoards / boardHash, now shared with the watcher in sp.ts.
  • Chat (ChatPanel.tsx): MadeBoards renders the buttons, folded to three rows, and sends sp:focus-board on the window.
  • Canvas (App.tsx): finds the canvas-file shape by its path, trying the board's own canvas first, then opens that canvas tab and calls zoomToFill. It goes by path rather than the library's id because an agent places boards under ids of its own in canvas.json.
  • Theme switch: ThemeSwitcher.tsx and theme.ts.

Stacked on #195. I'll retarget it to main once #195 merges.

Tested:

  • A dev server on port 5302 against a copy of a project, with a real Claude Code run that wrote a new board and ran sed on another. The reply showed 02 Whats New (green) and 04 Test Board (blue), and each button found its board.
  • A copy of a real project whose canvas the agent built in canvas.json: a 53-board reply folded to three rows, the toggle opened and closed the list, and buttons jumped across canvas tabs.
  • tsc and oxlint are clean. Tests: 189 passed, 1 skipped.

🤖 Generated with Claude Code

Jing-yilin and others added 2 commits September 27, 2026 05:29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hem on the canvas

The server hashes the project's boards when a run starts and again when it
ends, and the end event lists each board whose bytes changed, new or
rewritten. Off the files rather than the tool lines, which cannot say what
a generator wrote. The hashing the watcher did is now hashBoards in
boards.ts, shared by both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Deploying super-prototyping with  Cloudflare Pages  Cloudflare Pages

Latest commit: 84944df
Status: ✅  Deploy successful!
Preview URL: https://6e2ec674.super-prototyping.pages.dev
Branch Preview URL: https://jump-to.super-prototyping.pages.dev

View logs

Jing-yilin and others added 2 commits September 27, 2026 06:01
An agent places boards under ids of its own in canvas.json, so the library's id missed
them and the button did nothing. A generator rewriting every board made the list long.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Jing-yilin Jing-yilin changed the title Jump from a reply to the boards it made or changed Jump from a reply to the boards it made or changed, and a theme switch Sep 27, 2026
…r project, theme follows other windows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Jing-yilin
Jing-yilin changed the base branch from fullscreen-zoom to main October 8, 2026 00:06
@Jing-yilin
Jing-yilin marked this pull request as ready for review October 8, 2026 00:06
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 8 potential issues.

Devin Review

Comment thread canvas/src/tokens.css
Comment on lines +62 to +64
:root[data-theme="light"] {
color-scheme: light;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Light theme keeps dark colors

Selecting Light sets data-theme="light", but the later :root rule overrides its color scheme with dark. Tokens stay dark while tldraw switches to light, leaving the theme switch ineffective and the canvas mismatched.

Learn more

The page stores a theme on its root element, and its colors resolve through light-dark() in tokens. The new light and system rules precede the unconditional :root dark rule at the same specificity. The later rule wins, so neither new setting can change the page palette. Separately, handleMount switches tldraw to the selected theme, leaving its canvas unlike the surrounding controls.

Example: On a light OS, select Light. The switch indicates Light and tldraw gets a light scheme, but the top bar and chat still resolve their colors from the dark half of every token.

Recommended fix: Move the fallback color-scheme: dark to a :root:not([data-theme]) rule or place it before the specific theme selectors. Verify Light and System on both OS preferences.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread canvas/server/agent.ts
Comment on lines +113 to +114
const made = [...hashBoards(before.dir)]
.filter(([board, hash]) => before.hashes.get(board) !== hash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 New projects lose board jump buttons

When a first turn names an unnamed project, named moves its folder before the end event. hashBoards(before.dir) then sees no boards at the old path, so the reply has no jump buttons.

Learn more

An unnamed project starts in an Untitled folder. On a successful run, the child close handler calls named before it finishes the run. named moves the entire project folder, while before.dir still names the old canvases directory. hashBoards treats the missing directory as empty, and the end event loses all created or updated boards.

Example: Start a new Untitled project and ask the agent to name it and make canvases/launch/01-home.html on the first turn. The folder becomes its new project name, but the reply has no 01 Home button.

Recommended fix: Compute the after-hashes before calling named, or update the run's tracked directory when named moves it. Preserve the original before-hashes for the comparison.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +21 to +23
const follow = () => setTheme(storedTheme());
window.addEventListener("storage", follow);
return () => window.removeEventListener("storage", follow);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Other windows retain stale title bars

When another window changes the theme, follow updates the switch but never calls startup.theme. Electron's native title bar keeps its previous appearance until a local click or reload.

Learn more

The theme switch uses localStorage so every same-origin window receives a storage event. pickTheme notifies Electron when the local window changes the theme. The storage listener in this component updates its React state only. Thus another Electron window's selection reaches the switch but not the native title bar.

Example: Open the app's main window and a second app window, then choose Light in the second window. The main window's switch indicates Light, but its native title bar retains Dark.

Recommended fix: Have the storage-event handler notify startup.theme with the newly stored theme as well, or centralize native-theme synchronization in one listener.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread canvas/src/ChatPanel.tsx
Comment on lines +1422 to +1424
{t.end?.made && t.end.made.length > 0 && (
<MadeBoards made={t.end.made} away={t.project !== project} />
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Board links disabled on Home

After leaving a project for Home, project becomes undefined and every board button from that project is disabled. Completed replies cannot take the user back to their boards from Home.

Learn more

The chat remains mounted across tab and Home navigation in AppShell. project describes only what is currently open, not the project where a prior turn ran. The new button uses that equality to disable navigation, so a completed reply is not a usable route back to its project once the person leaves it.

Example: Send a turn from project Alpha that makes launch/01-home.html, go Home while it runs, then read the reply. Its board button is disabled even though Alpha and its board still exist.

Recommended fix: Route a click for a board in another project through the shell's project-tab navigation, then focus the board after its canvas frame mounts. Keep the buttons enabled for existing projects.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +15 to +16
export function ThemeSwitcher() {
const [theme, setTheme] = useState(storedTheme);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Release notes omit both new features

The theme switch and reply-to-board buttons need entries under Unreleased. The repository requires release notes in the same PR as user-facing changes.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread canvas/server/boards.ts
Comment on lines +19 to +20
export function hashBoards(canvasesDir: string) {
const list = (dir: string) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 New features have no adjacent tests

No tests accompany board hashing, run-end enrichment, or the theme switch. The repository asks for tests beside changed viewer modules.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

const [theme, setTheme] = useState(storedTheme);
// The app starts on the OS's until the page says, since the pick lives in the page's storage.
useEffect(() => window.startup?.theme(storedTheme()), []);
// Picked in another window of the same app, which shares the storage.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Storage listener comment repeats its code

The comment only describes the storage listener below it. Repository review rules reserve comments for non-obvious constraints.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread canvas/src/theme.ts
Comment on lines +21 to +27
/** This page's theme now, every other page's on the storage event, and the app's title bar's. */
export function pickTheme(theme: Theme) {
document.documentElement.dataset.theme = theme;
try {
localStorage.setItem(THEME_KEY, theme);
} catch {} // the pick then lasts only as long as this page
window.startup?.theme(theme);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Single-use theme helper

pickTheme has one caller, the switcher's click handler. Repository rules ask for single-use helpers to be inlined.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@Jing-yilin
Jing-yilin merged commit b76a786 into main Oct 8, 2026
11 checks passed
Jing-yilin added a commit that referenced this pull request Oct 8, 2026
Only the attach change had left its line under Unreleased. The rest is
reconstructed from the pull requests merged since v1.7.0: #195, #196, #197
and #198.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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