feat(#429): unify Dashboard creation and add the metadata rename pencil (phase 3) - #495
Merged
Merged
Conversation
…il (phase 3) Absorbs #481. `openNameDialog`/`openDialogShell` move out of file-menu.ts into a shared src/ui/dialog-shell.ts (generalized returnFocusTo + a single-slot staleness-guarded teardown) so the Dashboard tree's new rename pencil can reuse them. File > New dashboard... and the empty-workspace placeholder now both prompt and commit through appendDashboard, never the compatibility slot. A new renameDashboard planner + commitDashboardRename wrapper back a two-field title/description dialog on each Dashboard row's pencil. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018mujm1kW7jDGpTEfscndcU
This was referenced Jul 27, 2026
Open
This was referenced Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Part of #429 — phase 3, absorbing #481: Dashboard-document metadata gets
exactly one create path and its first rename affordance.
One Dashboard-creation path (#481)
File ▸ New dashboard… and the empty-workspace placeholder's Create button
disagreed: the File menu prompted for a name and committed through
appendDashboard; the placeholder appliedcreateEmptyDashboard's defaulttitle silently and wrote through
withCompatibilityDashboard/dashboards[0].Both now prompt through the same
openNameDialog(seeded with the sameDEFAULT_DASHBOARD_TITLE) and commit throughappendDashboard— no callerreaches the compatibility slot to create any more. The placeholder's dead
"collection already non-empty" guard is deleted rather than ported: once the
write is unconditionally additive, checking it first serves no purpose.
Dashboard-level metadata pencil
Each Dashboard row's new pencil (revealed on hover/
:focus-within, beside theexisting
⋯) opens a two-field dialog — title and description — prefilledfrom the current committed document. Cancel/Escape commit nothing; a blank
title disables Save; a real commit bumps only that Dashboard's revision and
refreshes the tree/any open Dashboard surface. There is still no Dashboard
trash action (non-goal, unchanged).
Implementation notes
openDialogShell/openNameDialogare promoted out offile-menu.tsinto anew
src/ui/dialog-shell.ts, so the Dashboard tree's pencil can reuse themwith no behavior change for File-menu's own dialogs. The hardcoded
app.dom.fileBtn!.focus()restore becomes an explicitreturnFocusToparam (File-menu's own wrapper still supplies
fileBtn); thedialogClosersWeakMap +
app.dom.fileDialogbookkeeping (now-dead field removed fromAppDom) becomes a single module-local "current open dialog" slot with itsown staleness guard, so a dialog opened from the tree — which, unlike
File-menu's own overlays, persists across Query/Dashboard surface switches —
is force-closed on a surface transition too.
renameDashboard(pure planner,workspace-dashboards.ts, modeled onwithVariableConfig) trims the title and refuses (commits nothing) on ablank-after-trim result — defense in depth alongside the dialog's own
disabled-confirm, since the schema itself carries no
minLengthfloor on aDashboard's
title.description: undefined(omitted) leaves the storedvalue untouched; an explicit string trims and omits the field once empty,
matching
renameSaved's convention.commitDashboardRename(
src/application/dashboard-title.ts) wraps it exactly likecommitVariableConfigwrapswithVariableConfig.display: noneexcept on hover/:focus-within, like the⋯it sits beside.By the time its own dialog closes, the pointer has typically moved onto the
dialog's controls, so neither still holds on the row — and
focus()on analready-hidden element is a silent no-op in a real browser (happy-dom
enforces no CSS layout at all, so the equivalent unit test passed regardless).
Fixed the same way
buildMenuButtonalready does it: the trigger's ownaria-expandedstays"true"for the dialog's whole lifetime, reveals itthrough the
openDialogShell'sreturnFocusTo.focus()call, and only resetsto
"false"afterward — by which point:focus-withincovers itindependently.
dialog-shell.tsgained anonClosehook for this.⋯(Library-row icon-order convention), gated bya new
DashboardTreeRow.renamablefield (true for the Dashboard row only) —keeping the row at two trailing controls, not three, so phase 5's "third icon
on a narrow row" concern isn't triggered here.
Acceptance criteria claimed
empty-Dashboard placeholder prompt for its name and append (Reconcile the two Dashboard-creation paths behind one action #481).
Deferred by design: panel-row edit/delete (phases 4/5), the repair planner
decision (phase 6), and every Dashboard-trash/deletion path (non-goal,
unchanged).
Verification
npm test— 179 files / 5877 tests passed, per-file coverage gate held;tsc --noEmitclean;npm run buildclean.npm run test:e2e(dashboard-tree.spec.js) — full spec green onchromium, webkit and firefox; the real-browser focus-restore bug above
was caught here first and is now pinned by a dedicated e2e test plus a unit
test on the
aria-expandedtoggle.test:e2esuite green on chromium (152/152); webkit clean; a handfulof unrelated Firefox specs (dashboard-kpi-move, dashboard-membership,
tile-open-workbench, variable-tab — none touched by this change) flaked
under full parallel load and passed individually on retry, matching known
sandbox Firefox flakiness.
staleness guard,
renameDashboard/commitDashboardRenamecorrectness,boundary rules, coverage-gate honesty, scope) came back with no defects.
ch-26.6): created a Dashboard via File ▸ New dashboard…, renamed it via the
pencil (title + description), confirmed the tree label updates, the toast
fires, and no console errors — including moving the mouse away right after
Save, to exercise the focus-restore fix above.
Checklist
npm testpasses (the per-file coverage gate is non-negotiable)npm run buildsucceeds (single-filedist/sql.html)src/core/, network insrc/net/(injected fetch), DOM insrc/ui/CHANGELOG.md([Unreleased]) updated if behavior or the deployed surface changed🤖 Generated with Claude Code
https://claude.ai/code/session_018mujm1kW7jDGpTEfscndcU