fix(#568): Dashboard tree — single revealed action cluster, inline count - #569
Merged
BorisTyshkevich merged 3 commits intoJul 29, 2026
Merged
Conversation
…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
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.
Summary
:focus-withinnever 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.· Ncount (Sales revenue · 2) rendered as a right-aligned column instead of inline right after the label, unlike the Library tab'sLibrary · 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 --noEmitnpx 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-dependentrelative-time.test.tsfailures reproduced identically on unmodifiedmain, unrelated to this change)npx playwright test tests/e2e/dashboard-tree.spec.json 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🤖 Generated with Claude Code
https://claude.ai/code/session_01MbJW6B535ebEZjZRgaBZy8