Files
platform/todo/url-state/_index.md
T
pastilhasandClaude Fable 5 bd9d26199f the ephemeral pane is open when it exists, not when an effect says so
Refresh on /files/...?view=x.m4a came back with the query string intact and no
viewer, and then double-clicking the file did nothing at all. Two symptoms, one
cause, and the second is what made it read as a click bug.

WorkspaceView gave the pane defaultSize={0} and opened it from an effect calling
panel.resize(), so open/closed was expressed twice — the markup said closed and
the effect was meant to correct it. A correction step can be missed, and this one
was: on a deep link isEphemeralOpen is true on the first render, but
workspace.isLoaded is false until /dashboards answers and the early return means
nothing is rendered, so the effect ran against a null ref and returned. Its deps
were [isEphemeralOpen, defaultBaseSize] — one already true, the other a constant
— so it never ran again. URL open, pane at zero width.

Then the inert double-click follows for free: ?view= already held that name, so
setSearchParams changed nothing, so there was no transition for the effect to
react to. The URL being already correct is exactly why the click had nothing to
say.

Now the pane is rendered conditionally with id + order — the same pair
WorkspaceRenderer already uses — and both panels take declarative sizes. There is
no moment where markup and intent disagree, and a deep link is right on first
paint rather than corrected after it. The try/catch that guarded resizing an
unlaid-out group goes with it; nothing calls resize now.

ephemeral-pane.test.tsx asserts the SIZE the group computes, not that the element
exists — a pane at zero width satisfies any is-it-in-the-document check, which is
the failure being guarded against. Five of its six tests fail against the old
implementation, including the load-order one. Full suite: 1316 pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 21:11:15 +00:00

2.6 KiB

theme, heading, kind
theme heading kind
url-state URL state — routing, query strings and selection theme

Grouped 2026-08-21. This was files-app, and the file browser is still where most of it is — but the question underneath is not the file browser's. Where selection lives, what a query string is allowed to mean, and who is responsible for clearing one are framework questions that happen to have been answered first in /files. The panel framework's own version of the same question is here too, rather than filed under the framework's deep read where nobody comparing the two would find it.

docs/navigation-audit.md is the authority for all of it.

The URL model is done (2026-08-15). The folder is the pathname — /files/archive/Tests/platform/docs — and ?view= is a NAME within it, not a second copy of the path. Deep links and refresh work, which they never had. Landed across 559560de, 98ba604a, 7e31564c, 0dc88b51, 7359af2f, with files-route.ts + 23 tests as the one owner of encoding and of which params belong to the overlay.

Four bugs came out of that work and are fixed: closing a pane sent you home; ?view= was stripped on every page load by a mount effect that had made deep links impossible since 2026-02-23; navigating kept a pane belonging to the folder you left; and the breadcrumb opted out of that last rule because it is a <Link> and never called the function enforcing it.

A fifth, fixed 2026-08-21. The URL survived a refresh and the pane still did not open — reported as "refresh loses the panel, and then the file won't open". Nothing to do with the query string this time: WorkspaceView gave the ephemeral pane defaultSize={0} and opened it from an effect calling panel.resize(), so open/closed lived in two places. On a deep link the effect ran before workspace.isLoaded was true — when the early return means nothing is rendered and the ref is null — and its deps could not change afterwards, so it never ran again. The second half is what made it look like a click bug: with ?view= already naming the file, double-clicking it changed no state, so nothing re-ran. The pane is now rendered conditionally with id + order and sized declaratively; ephemeral-pane.test.tsx asserts the SIZE rather than the element's presence, because a pane at zero width passes any "is it in the document" check. Five of its six tests fail against the old implementation.

The shape is worth keeping in mind for the rest of this theme: state that the URL owns, mirrored into an imperative correction, will eventually be read at a moment the correction cannot run.