Feat/add close all tabs - #2863
Conversation
|
This comment was marked as outdated.
This comment was marked as outdated.
| function moveFocus(direction) { | ||
| const items = [...$el.children]; | ||
| if (!items.length) return; | ||
|
|
||
| const currentIndex = items.indexOf(document.activeElement); | ||
| let nextIndex; | ||
| if (currentIndex === -1) { | ||
| nextIndex = direction > 0 ? 0 : items.length - 1; | ||
| } else { | ||
| nextIndex = (currentIndex + direction + items.length) % items.length; | ||
| } | ||
| items[nextIndex]?.focus(); |
There was a problem hiding this comment.
Disabled Items Stay Actionable
Keyboard navigation treats every direct child as an action, including separators and entries marked disabled. Arrow, Home, and End keys can focus <hr> elements, while Enter or Space can dispatch a click on a disabled entry. Existing menu handlers do not check the disabled state before running its command, so keyboard users can trigger actions that the menu presents as unavailable. Navigation and activation should be limited to enabled action items.
Knowledge Base Used:
This comment was marked as outdated.
This comment was marked as outdated.
| * Close the tab of the given file (which may not be the active file). | ||
| */ | ||
| "close-tab"(referenceFile) { | ||
| const file = resolveReferenceFile(referenceFile); |
There was a problem hiding this comment.
A stale menu can close the wrong tab. close-tab uses resolveReferenceFile(), which falls back to activeFile when an explicit ID no longer exists. If the referenced tab closes while its menu remains open, selecting “Close file” closes the newly active tab instead.
| * @param {HTMLElement} $item | ||
| */ | ||
| function activateItem($item) { | ||
| if (!$item || !$el.contains($item)) return; |
There was a problem hiding this comment.
Disabled items remain keyboard-actionable. Navigation includes every child, including hr separators and .disabled rows. Programmatically dispatching a click bypasses CSS pointer-events: none, allowing disabled commands such as Save, File Info, or Encoding to execute. Restrict navigation and activation to enabled actionable rows.
| case "Enter": | ||
| case " ": | ||
| case "Spacebar": | ||
| e.preventDefault(); |
There was a problem hiding this comment.
Nested controls lose keyboard behavior. The shared keydown handler intercepts Space/Enter from any descendant. When the file menu’s read-only checkbox has focus, getFocusedItem() returns null, but preventDefault() still blocks the checkbox from toggling. Handle activation only when focus is on a direct menu row, or ignore events originating from interactive descendants.
Summary
Adds a context menu to file tabs, opened via long press (touch) or right click (desktop) to quickly close the current file, all open files in the group, or all tabs to the left/right of the pressed tab.
What's changed
src/handlers/editorFileTab.js— Distinguishes a long press from an actual tab drag using a pointer-slop threshold. When a press ends without moving (didDrag === false), the drag is finished and the tab context menu is opened instead.src/handlers/tabContextMenu.js(new) — Renders and positions the context menu next to the pressed tab, flipping horizontally/vertically when near the screen edge. It also guards against synthetic "click" events fired after touch gestures so menu items aren't accidentally activated on release.src/lib/editorFile.js— Wires up the context menu for both layouts:openTabContextMenuOnRelease).src/lib/commands.js— Adds two commands that run throughacode.exec(so the same prompts/flows as the rest of the app are used):close-tab— close the specific pressed file (not necessarily the active one).close-tabs-in-group— close every tab in the pressed file's pane/tab group; in the sidebar layout this closes all open files.close-tabs-to-left/close-tabs-to-right.Menu options
close-tabclose-tabs-in-groupclose-tabs-to-leftclose-tabs-to-rightTesting
Notes
strings(e.g.close file,close all) when translations exist; a hard-coded fallback is used otherwise.