Skip to content

feat: rebuild the dock as Health, Activity and Structure views - #45

Draft
lxsmnsyc wants to merge 10 commits into
mainfrom
feat/dock-redesign
Draft

lxsmnsyc wants to merge 10 commits into
mainfrom
feat/dock-redesign

Conversation

@lxsmnsyc

@lxsmnsyc lxsmnsyc commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

What and why

The dock had a sidebar of seven panels. This rebuilds it as three views, following the approved prototype: Health, Activity and Structure. Each view uses the prototype's layout, not the old panels under a new header.

Changes

Header and pull tab

  • The header shows the logo, the solid-js version, the route, the three views (Health shows its error and issue counts), the search box, and the tools. The "Start Devtools" title and the toolbar version are gone.
  • The closed state is still the bottom-edge grip. Its pull tab shows the solid-js version and the counts.
  • ⌘K (Ctrl+K), while the dock is open, finds components, memos, signals, actions and server functions by name, with live values. Picking one opens it in its view.

Health

  • One list of thrown errors and runtime issues, with search, the chips All / Errors / Warnings / Info, Clear, and an "N of M" count.
  • An error shows the function it was thrown in, the time it was caught, and the action it was caught during, with a link to it in Activity. Below that are the stack frames beside the source, with library frames folded, the column marker, Original/Compiled and "Open in editor". The pager, GitHub, Discord, screenshot, copy report and reset stay.
  • An issue uses the same header, with its details and links.

Activity

  • One stream of actions, server-function calls, async loads, waits and fallbacks, and errors from the last 30 seconds, with:
    • a live lanes strip on a fixed time axis (−30s to now), where items slide left and fall off; drag on it to filter the list to a window
    • a pause button that freezes what is shown; a selected item stays listed until deselected
    • filter chips and time groups
    • repeated actions folded into one row
  • An action shows:
    • its event, time and outcome
    • the Wrote → Re-ran → Effects chain
    • its interaction timings
    • waterfalls of its re-runs and server calls
    • its holds
    • buttons to open the file, show the node in Structure, and copy a report
  • Server calls and async records open their existing detail in the same pane.

Structure

  • Owners (the ownership tree) and Graph (the reactivity graph, unchanged) are chips at the top of the view.
  • Tree rows show signal and memo counts and a heat dot for how recently and how often their computations update. Same-name siblings fold into Name #3 … #8.
  • "Hide Solid internals" folds Solid's own components (For, Show and others) away.
  • The detail lists props, signals and memos with kind chips and editable values, a signal's previous value and when it changed, and "N updates, last Xs ago".
  • Pause, expand all, collapse all and the count stay.

Fixes made along the way

  • Timeline retention: the timeline and the async history keep everything from the last 30 seconds instead of 100 and 200 entries, with safety caps of 5000 and 1000. An animation loop no longer pushes clicks out. A fast run of one action draws as one bar.
  • Activity cost: the view redraws from a sample at most every 250ms. With a 60fps loop and about 1875 entries, script time went from 233ms to 61ms per second while the loop ran. One 250ms update with the loop stopped went from about 55ms to 4.4ms.
  • Toolbar activity: the toolbar's own fallbacks and loads, and clicks on its pull tab, no longer show up as app activity.
  • Value editor: it no longer overflows the stack when a panel hands it the hidden signal it writes through.
  • Old dock state: widths and tabs saved by earlier versions map to the new views.

Decisions taken with the maintainer

  • Action location: taken from the first write's stack (stacks: true on attribution). With a prebundled solid-js, the normal Vite dev setup, the runtime keeps only engine frames, so the location and the "Open" button are hidden there.
  • Chain's last box: shows the effects that ran, not a DOM node count.
  • Structure detail: shows the update count and the last update, not "rendered N times". Solid runs components once.
  • Error header: says where an error was thrown, not which boundary caught it. configureClientErrors would replace the app's own hook.
  • Health filters: search and the severity filter stay, fitted to the prototype.

Proof

  • pnpm format:check, pnpm typecheck, pnpm build and pnpm test (297 tests) pass.
  • pnpm test:e2e passes (23 tests). The spec was updated for the new selectors and views.
  • New pure modules with tests: activity/model.ts, ownership/heat.ts, ownership/runs.ts, ownership/builtins.ts, palette/search.ts, timeline/group.ts, structure/signal-history.ts, health/time.ts, error-viewer/frames.ts.
  • Each view was compared with the prototype in the demo app.

Cost

  • There are no new dependencies. Each view and the palette is a lazy chunk.
  • Write stacks add a cost to each write while the timeline listens. I did not measure it.

Not done

  • ownership/heat.ts formatAgo and health/time.ts formatAge overlap. They round differently and could share one helper.

Review

  • Rebased on fix: leave out errors thrown by browser extensions #46 (extension errors) and fix: keep the 200 newest errors #47 (the 200-error cap). Error records go through the same cap, and the two tests they added now open the Health view.

  • I reviewed it with a fresh agent using the pr-review skill: no blocking findings.

  • I fixed both should-fix items: the Health age clock now runs only while the view is shown, and a new error is detected by its record, not the count.

  • The nits are listed above.

🤖 Generated with Claude Code

@lxsmnsyc lxsmnsyc changed the title feat: group the dock panels into Health, Activity and Structure views feat: rebuild the dock as Health, Activity and Structure views Nov 4, 2026
lxsmnsyc and others added 10 commits November 4, 2026 13:18
The dock header switches between three views instead of a sidebar of seven
tabs. Health lists thrown errors and runtime issues together, with the
selected entry beside the list. Activity holds Timeline, Async and Server
functions, and Structure holds Ownership and Reactivity.

The header and pull tab show the solid-js version instead of the toolbar's
title and version. The error panel lists frames beside the source, folds
library frames and opens frames in the editor. The timeline folds runs of
the same action. Every list and detail split uses the resize handle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…totype

The views keep the approved prototype's layout instead of the old panels.

- Activity merges actions, server calls, async records and errors into one
  stream with a lanes strip, filter chips, time groups and folded repeats.
  An action shows its writes, re-runs and effects, waterfalls of re-runs
  and server calls, its interaction, holds and outcome.
- Health lists errors and issues with search and severity chips. An error
  shows where it was thrown, when, the action it happened in, the stack
  beside the source and "Open in editor".
- Structure switches between the ownership tree and the reactivity graph.
  Rows show counts and update heat, Solid's own components fold away, and
  the detail lists props, signals and memos with a signal's last change.
- A ⌘K palette finds components, signals, memos, actions and calls.
- The header has the three views and the search box, and errors keep
  when they were caught and the action they happened in.

Fixes found along the way: the timeline drops repeats of one label before
distinct actions when full, the toolbar's own fallbacks and pull-tab clicks
stay out of Activity, and the value editor no longer recurses when a panel
hands it its own bridge node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lanes strip covered the oldest to the newest record and rescaled as
entries were dropped, so actions seemed to vanish. It now covers the last
30 seconds on a fixed axis with -30s, -20s, -10s and now, and items slide
left as time passes. The list shows the same window, and a selected item
stays until it is deselected. Pause freezes what is shown, even while the
stores drop old records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The timeline kept 100 entries and the async history its own count, so a
loop such as an animation frame pushed actions out of the window within a
second. Both now keep everything from the last 30 seconds, with a large
safety cap. A fast run of one action draws as one bar on the strip, and the
view redraws from a sample at most every 250ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The source view drew a ^ under the column. The highlighter's err marker
already wraps the exact expression, so it is drawn as an error squiggle
and the lines around it step back.

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