Skip to content

Feat/add close all tabs - #2863

Open
TonyGeez wants to merge 6 commits into
Acode-Foundation:mainfrom
TonyGeez:feat/add-close-all-tabs
Open

Feat/add close all tabs#2863
TonyGeez wants to merge 6 commits into
Acode-Foundation:mainfrom
TonyGeez:feat/add-close-all-tabs

Conversation

@TonyGeez

@TonyGeez TonyGeez commented Sep 8, 2026

Copy link
Copy Markdown

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:
    • Tab-bar layout (top/bottom): long press starts a drag; the menu opens when the drag ends without movement.
    • Sidebar layout: no tab drag, so the menu opens when the pointer is released (openTabContextMenuOnRelease).
  • src/lib/commands.js — Adds two commands that run through acode.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.
    • Reuses existing close-tabs-to-left / close-tabs-to-right.

Menu options

Option Action
Close file close-tab
Close all close-tabs-in-group
Close Left close-tabs-to-left
Close Right close-tabs-to-right

Testing

  • Long press a tab in the top tab-bar layout → menu opens, no accidental reorder/drag.
  • "Close all" closes every open file.
  • "Close Left"/"Close Right" close only the expected tabs.
  • Dragging a tab still works normally (no menu appears after a real drag).

Notes

  • New tab labels fall back to strings (e.g. close file, close all) when translations exist; a hard-coded fallback is used otherwise.
  • Menu positioning uses size estimates; exact placement may need minor tuning on very large/small screens.

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no new blocking issue was identified, though the existing non-blocking keyboard handling concern remains outstanding.

Findings

  1. P2 Disabled Items Stay Actionable

Summary

  • Opens the menu by long press on touch devices or right click on desktop.
  • Distinguishes stationary long presses from tab-drag gestures using an 8px movement threshold.
  • Routes close operations through shared commands so existing confirmation and file-removal behavior is preserved.
  • Adds shared keyboard navigation and activation support to the context-menu component.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Long press or right click tab] --> B{Tab-bar layout?}
  B -->|Yes| C[Start drag session]
  C --> D{Movement exceeds 8px?}
  D -->|Yes| E[Complete tab drag]
  D -->|No| F[Open tab context menu]
  B -->|No, sidebar| G[Wait for pointer release]
  G --> H{Movement exceeds 8px?}
  H -->|Yes| I[Cancel menu request]
  H -->|No| F
  F --> J[Close file / group / left / right]
  J --> K[Execute shared Acode command]
Loading

Reviews (3) · Last reviewed commit: "Merge branch 'Acode-Foundation:main' int..."

Comment thread src/handlers/tabContextMenu.js
Comment thread src/handlers/tabContextMenu.js
@bajrangCoder

This comment was marked as outdated.

Comment on lines +143 to +154
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();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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:

@bajrangCoder

This comment was marked as outdated.

Comment thread src/lib/commands.js
* Close the tab of the given file (which may not be the active file).
*/
"close-tab"(referenceFile) {
const file = resolveReferenceFile(referenceFile);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

@bajrangCoder bajrangCoder Sep 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants