Tree View Hover Row Actions — Delivery Notes
Hover rename and delete buttons on every tree-view file/folder row, so those don’t require the right-click context menu — plus a fix so the folder-count pill (and the new buttons) stay visible at the panel’s right edge instead of scrolling off with long filenames. No ADR: this is a UI affordance, not an architectural decision. All in tranquil-automations.
Status
Implemented and iterated to final in a running window. Toggle: Settings →
tranquil-automations → Show Rename/Delete Buttons on Tree View Rows (showRowActions, default on).
What shipped
lib/row-actions.js(new) — on hover, injects a small.tq-row-actionsgroup (pencil + trash, inline SVGs) into the hovered row and removes it on leave (only one row decorated at a time). Buttons reuse the nativetree-view:rename/tree-view:removecommands (so the real rename dialog and delete confirmation come for free) after selecting the row onmousedown.lib/folder-counts.js— the count pill is now pinned to the visible right edge too, and yields (hides) while a row shows its action buttons.lib/tranquil-automations.js—showRowActionsconfig + conditional activation (mirrorsshowFolderCounts).styles/tranquil-automations.less— the chip + button styling.
The hard parts (and why)
- Positioning:
position: fixed+ JS, not CSS. The tree-view scrolls horizontally (rows aremin-contentwide) and rows are not flex — so a row-relativeright:runs off-screen for long names, andposition: stickywon’t pin (a short row’s natural end is right after the name). Both the buttons and the pill are therefore placed by JS from the tree-view’s viewport rect (getBoundingClientRect), re-run on hover/scroll/resize. The button group stays a DOM child of the row so it inherits the row’s text color and hovering it still counts as hovering the row. - One injector owns the tree observer. An early version gave row-actions its own
MutationObserver; it cross-triggered folder-counts’ observer (each one’s writes woke the other), corrupting both on expand/collapse. Fixed by making row-actions injection hover-driven (a delegatedmouseover, no observer) and letting folder-counts remain the single tree observer. Pill-vs-buttons overlap is resolved in folder-counts (it hides its badge when a.tq-row-actionsis present in the header), so there’s one authority, no opacity race. - Theme quirks ([[theme-development]]):
- The business themes don’t export ui-variables, so the chip’s opaque backdrop is read at runtime
via
getComputedStyle(treeView).backgroundColor(theme-agnostic, keeps the filename from showing through), and the icons usecolor: inherit. - The business
base.lessstyles barebutton { background: … !important }/button:hover { … !important }, so the button fills need!importantto win — the usual “avoid !important” guideline is overridden here because we’re beating a theme’s own!important.
- The business themes don’t export ui-variables, so the chip’s opaque backdrop is read at runtime
via
Behaviour notes
- Project roots are skipped (no rename/delete on a root). A file with no pill just gets buttons.
- Delete keeps the native “Move to Trash” confirmation; rename opens the native dialog.
- Hover fills: blue = rename, red = delete (white icon, slight pop + coloured glow); the two are spaced so a hovered button’s glow doesn’t reach its neighbour.