Skip to content

feat: inspector UX — publishers follow unit selection, draggable divider - #8

Merged
cboulay merged 3 commits into
devfrom
feat/publisher-focus-on-unit-click
Aug 14, 2026
Merged

cboulay merged 3 commits into
devfrom
feat/publisher-focus-on-unit-click

Conversation

@cboulay

@cboulay cboulay commented Aug 14, 2026 •

Copy link
Copy Markdown
Member

Two inspector UX changes. Stacked on #6 (base is fix/frontend-typecheck), so the diff here is just the five files below.

CI does not run on this PR: both workflows trigger only on pull requests targeting main or dev. Retarget once the stack below it merges. Verified locally — see Verification.

1. Selecting a unit also focuses the Publishers list

Clicking a unit in the topology already snapped Settings to that component and expanded it. Now Publishers follows too: every row whose owning component is the selected unit is expanded, and the first is scrolled into view.

ProfilingPanel already did this for publisher-stream and subscriber-stream selections, so rather than repeat the expand-and-scroll block a third time, the three branches now share a revealRows(matchedIds, contributorEndpointId) helper. The new branch matches on row.unitAddress, which the panel already resolves from the graph snapshot for every publisher row.

Two deliberate choices:

  • The Publishers section's collapsed state is left alone. Collapsing a section is a deliberate "maximize the other one" action, so a unit click shouldn't undo it. The panel is unmounted while collapsed, so it picks the pending request up when expanded again — the focus is deferred, not lost.
  • A focus request that matches no rows is not marked handled, so a unit whose publishers only appear in a later snapshot still gets focused when they arrive. That's the pre-existing behavior of the other two branches, preserved by the shared helper.

Collections are untouched — their streams belong to their child units, so selecting one still focuses Settings only.

2. The inspector divider can be dragged

The split between the topology and the inspector was only adjustable through the Inspector Width number field buried in global settings. The border between them is now a real divider:

  • Drag it to trade width between the two panes.
  • Double-click to return to the default (500px).
  • Arrow keys when focused — ←/→ move 16px, Home/End jump to the widest/narrowest inspector. It's a role="separator" with aria-valuenow/min/max, so the current width is announced.

The width still lives in globalSettings.inspectorWidthPx, so it persists and stays in sync with the existing number field. The 360–900px clamp — until now spelled out separately in three places — is a single clampInspectorWidth.

Implementation notes:

  • One localStorage write per drag, not per frame. The live width is held in component state during the drag and committed to global settings on release.
  • The handle overlays the existing border (position: absolute; left: -3px; width: 7px) instead of taking its own grid column, so nothing shifts when it appears and the collapsed-inspector layout is untouched. It isn't rendered while the inspector is collapsed.
  • Pointer capture keeps the drag tracking outside the 7px strip and stops the topology from panning underneath. An is-resizing-inspector class suppresses text selection and holds the col-resize cursor for the duration.
  • Resizing deliberately does not re-fit the topology view, matching what the number field has always done — a re-fit would throw away the user's pan/zoom. Easy to change if you'd rather it re-fit on release.

Verification

  • npm run test:e2e: 28 passed, including four new tests:
    • a unit click expands its publisher row (asserted hidden before the click, so it can't pass vacuously),
    • a real drag from 500 → 620px, with the topology taking exactly the remaining width and 620 landing in localStorage,
    • the clamp plus double-click reset,
    • keyboard resizing with the aria-valuenow readout.
  • npm test: 35 passed. npm run build: clean.
  • The divider was also driven by hand against the dev server (idle / hover / drag).

Two notes on the tests: the drag asserts persistence by reading localStorage rather than reloading, because the primeGlobalSettings init script re-primes the width on every navigation — there's a comment saying so. And the publisher-focus scroll isn't asserted, because no fixture has enough publisher rows for the list to overflow; the scrollIntoView call is the one the existing focus paths already make through the shared helper.

Possible follow-up

Selecting a unit from the Settings list (rather than the topology) still leaves Publishers where it is. Making that symmetric is a one-line change, but it would rearrange the Publishers list on every click while browsing settings, so I left it out.

Packaged assets (last commit)

src/ezmsg/dashboard/_web is a committed copy of frontend/dist (see #5 and #6). The last commit rebuilds it so the packaged dashboard actually serves these UX changes — inspector-resize-handle is present in the bundle — and so the staleness check added in #6 stays green.

🤖 Generated with Claude Code

@cboulay
cboulay force-pushed the feat/publisher-focus-on-unit-click branch from 9f7544e to cc68d5a Compare August 14, 2026 16:49
@cboulay cboulay closed this Aug 14, 2026
@cboulay
cboulay deleted the feat/publisher-focus-on-unit-click branch August 14, 2026 16:53
@cboulay cboulay changed the title feat: focus the publishers list when a unit is selected feat: inspector UX — publishers follow unit selection, draggable divider Aug 14, 2026
@cboulay
cboulay restored the feat/publisher-focus-on-unit-click branch August 14, 2026 16:54
@cboulay cboulay reopened this Aug 14, 2026
@cboulay
cboulay force-pushed the fix/frontend-typecheck branch from 4c23007 to df91ca3 Compare August 14, 2026 18:56
cboulay and others added 3 commits August 14, 2026 14:56
Clicking a unit in the topology already snaps the Settings panel to that
component. Do the same in Publishers: reveal every row whose owning component
is the selected unit, and scroll the first one into view.

The panel already had this machinery for publisher and subscriber stream
selections, so the three focus branches now share one `revealRows` helper
rather than repeating the expand/scroll block a third time.

Two deliberate choices:

- The Publishers section's collapsed state is left alone. Collapsing a section
  is a deliberate "maximize the other one" action, so a unit click should not
  undo it -- the panel is unmounted while collapsed and picks the request up
  when it is expanded again.
- A focus request that matches no rows is not marked handled, so a unit whose
  publishers only show up in a later snapshot still gets focused then.

Collections are untouched: their streams belong to their child units, and
selecting one continues to focus Settings only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The split between the topology and the Publishers/Settings inspector was only
adjustable through the `Inspector Width` number field in global settings. Make
the border between them a real divider: drag it to trade width between the two,
double-click to return to the default, or focus it and use the arrow keys
(`Home`/`End` jump to the extremes).

The width still lives in `globalSettings.inspectorWidthPx`, so it persists and
stays in sync with the existing number field, and the 360-900px clamp -- until
now spelled out separately in three places -- is a single `clampInspectorWidth`.

While dragging, the live width is held in component state and only committed to
global settings on release, so a drag is one localStorage write rather than one
per frame. The handle overlays the existing border rather than taking a grid
column, so nothing shifts when it appears.

Resizing deliberately does not re-fit the topology view, matching what the
number field has always done -- a re-fit would throw away the user's pan/zoom.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Picks up the publishers focus and draggable divider changes so the packaged
dashboard serves them, and keeps the new CI staleness check green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cboulay
cboulay force-pushed the feat/publisher-focus-on-unit-click branch from 9f7544e to 7dae678 Compare August 14, 2026 18:56
Base automatically changed from fix/frontend-typecheck to fix/nonfinite-float-settings August 14, 2026 23:09
Base automatically changed from fix/nonfinite-float-settings to dev August 14, 2026 23:09
@cboulay
cboulay merged commit e4b55e6 into dev Aug 14, 2026
@cboulay
cboulay deleted the feat/publisher-focus-on-unit-click branch August 14, 2026 23:10
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