Skip to content

fix(#568): Dashboard tree — single revealed action cluster, inline count - #569

Merged
BorisTyshkevich merged 3 commits into
mainfrom
fix/dashboard-tree-row-icons-and-count-568
Jul 29, 2026
Merged

fix(#568): Dashboard tree — single revealed action cluster, inline count#569
BorisTyshkevich merged 3 commits into
mainfrom
fix/dashboard-tree-row-icons-and-count-568

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

Summary

  • The Dashboards sidebar tree could show two rows' pencil/trash action clusters revealed at once: a merely-clicked (selected) row's :focus-within never cleared, so it stayed lit alongside whatever row the pointer was hovering. The reveal rule now uses :has(:focus-visible), which only real keyboard navigation grants — reachability for keyboard users is unchanged, but a plain click no longer pins a row's actions open.
  • The · N count (Sales revenue · 2) rendered as a right-aligned column instead of inline right after the label, unlike the Library tab's Library · 66 — despite the model already documenting inline as the intent. Label + count now share one flex group so only that group grows; the label still ellipsizes.

Closes #568.

Test plan

  • npx tsc --noEmit
  • npx vitest run --config tests/vitest.config.ts tests/unit/dashboard-tree.test.ts (187 passed)
  • npx vitest run --config tests/vitest.config.ts (full suite: 6655 passed; 14 pre-existing timezone-dependent relative-time.test.ts failures reproduced identically on unmodified main, unrelated to this change)
  • npx playwright test tests/e2e/dashboard-tree.spec.js on chromium, firefox, webkit (102/102 passed), including two new regression tests: one asserting a clicked row's actions go invisible once the pointer hovers elsewhere, and one asserting the count sits geometrically adjacent to the label
  • Manually verified in a real browser (agent Chrome against the Playwright e2e harness): clicking a row then hovering another shows only the hovered row's actions; Tab-focusing a row's action button still reveals it; counts read inline after the name

🤖 Generated with Claude Code

https://claude.ai/code/session_01MbJW6B535ebEZjZRgaBZy8

BorisTyshkevich and others added 3 commits July 29, 2026 21:02
…e, and put the count back inline

.dash-tree-row:focus-within .dash-tree-act revealed a row's pencil/trash on
ANY focus, so a merely-clicked (selected) row kept its actions visible
forever alongside whatever row the pointer was hovering. Swapped to
:has(:focus-visible), which real keyboard Tab/Arrow still grants but a
pointer click does not, so exactly one row's actions show at a time while
keyboard reachability is unchanged.

Separately, the `· N` count was a flex sibling of a flex:1 label, so it (and
everything after it) got pushed into a right-aligned cluster instead of
sitting inline after the name as dashboard-tree-model.ts already documented
as the intent and the Library tab already does. Label + count now share one
flex group so only that group grows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbJW6B535ebEZjZRgaBZy8
:has()'s argument is an implicit descendant selector, so
.dash-tree-row:has(:focus-visible) alone missed the row's OWN roving-tabindex
focus (what a real ArrowDown/ArrowUp or the first Tab into the tree lands on,
before a chevron or action button is reached) — verified live: arrowing onto
a row left its pencil/trash at opacity 0 until you tabbed further onto a
child control. Added :focus-visible (self) alongside :has(:focus-visible)
(descendant), and a regression test that arrows onto a row and asserts its
actions are revealed without a descendant control being focused.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbJW6B535ebEZjZRgaBZy8
ChatGPT's review of this PR (verified independently) caught a real CI
regression: full-suite e2e on chromium was failing 199/200 on
tests/e2e/tile-open-workbench.spec.js's "Panels-row plus" test, which
programmatically .focus()es the action button directly and expects it to
reveal at opacity 1 — a pre-existing contract the sibling .dash-tile-actions
family's "Focus alone reveals it" test also relies on. My earlier fix only
verified the single dashboard-tree.spec.js file locally, not the full e2e
suite CI actually runs, so this slipped through.

Root cause: :focus-visible/:has(:focus-visible) require real keyboard
modality, but a bare programmatic .focus() with no preceding keyboard event
doesn't grant it. Added .dash-tree-act:focus (plain, not :focus-visible) to
the reveal rule: it only reveals the ONE button that itself holds focus,
never a sibling or the whole row, so it cannot resurrect the original
stale-row-selection bug.

Also hardened the count-adjacency e2e assertion (added a lower bound; moved
the upper bound off the old layout's exact 8px gap, which risked a
sub-pixel-rounding false pass), split the arrow-navigation regression test to
explicitly isolate the pointer-to-keyboard modality transition, added a test
for the :has() descendant-focus branch specifically, and fixed a comment in
the drag handler left stale by the label/count DOM restructuring.

Full e2e suite (all spec files) now passes on chromium, firefox, and webkit
(392/392, 8 skipped as before for unsupported Firefox isMobile emulation) —
previously only the single dashboard-tree.spec.js file had been run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MbJW6B535ebEZjZRgaBZy8
@BorisTyshkevich
BorisTyshkevich merged commit e618dc2 into main Jul 29, 2026
8 checks passed
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.

Dashboard tree: two revealed action clusters at once, and the count reads as a right-aligned column

1 participant