update right click menu
Some checks failed
CI / check (push) Has been cancelled

This commit is contained in:
2026-06-20 21:08:42 +02:00
parent 6114ce440d
commit fb4018336f
3 changed files with 25 additions and 7 deletions

View File

@@ -513,18 +513,32 @@ export function App(): React.ReactElement {
} }
function openMenu(e: React.MouseEvent, target: ContextTarget): void { function openMenu(e: React.MouseEvent, target: ContextTarget): void {
e.preventDefault(); e.stopPropagation() e.preventDefault(); e.stopPropagation()
openMenuAt(e.clientX, e.clientY, target) // Editor menus open right at the cursor. Tree/git row menus instead anchor to
// the right edge of the whole column (matching the ⌘→ keyboard menu) so the
// opaque menu floats entirely beside the list — it must never reach back over
// the rows, or it hides the file directly under the one you right-clicked.
if (target.kind === 'editor') { openMenuAt(e.clientX, e.clientY, target); return }
openMenuAt(rowAnchorX(e.currentTarget as HTMLElement), e.clientY, target)
}
// Left edge for a tree/git row menu: the right edge of the row's column, so the
// menu sits clear of every row in that column (robust to horizontal scroll and
// narrow columns, where the row's own right edge can fall under the rows).
function rowAnchorX(row: HTMLElement): number {
const col = row.closest('.col') as HTMLElement | null
return (col ?? row).getBoundingClientRect().right
} }
// ⌘→ inside Git/Explorer: open the selected row's menu, anchored to its row. // ⌘→ inside Git/Explorer: open the selected row's menu, anchored to its row.
function openPanelMenu(): boolean { function openPanelMenu(): boolean {
if (activePanel === 'git' && gitSelPath) { if (activePanel === 'git' && gitSelPath) {
const r = document.querySelector('.git-row.kbd')?.getBoundingClientRect() const row = document.querySelector('.git-row.kbd') as HTMLElement | null
openMenuAt(r ? r.right - 40 : 220, r ? r.top + 4 : 120, { path: gitSelPath, kind: 'git', staged: proj.staged.has(gitSelPath) }) const r = row?.getBoundingClientRect()
openMenuAt(row ? rowAnchorX(row) : 220, r ? r.top + 4 : 120, { path: gitSelPath, kind: 'git', staged: proj.staged.has(gitSelPath) })
return true return true
} }
if (activePanel === 'tree' && treeSelItem) { if (activePanel === 'tree' && treeSelItem) {
const r = document.querySelector('.tree-row.kbd')?.getBoundingClientRect() const row = document.querySelector('.tree-row.kbd') as HTMLElement | null
openMenuAt(r ? r.right - 40 : 220, r ? r.top + 4 : 120, { path: treeSelItem.path, kind: treeSelItem.type }) const r = row?.getBoundingClientRect()
openMenuAt(row ? rowAnchorX(row) : 220, r ? r.top + 4 : 120, { path: treeSelItem.path, kind: treeSelItem.type })
return true return true
} }
return false return false

View File

@@ -469,7 +469,7 @@ export function ContextMenu({ menu, onClose }: { menu: Menu | null; onClose: ()
const x = Math.min(menu.x, window.innerWidth - 270) const x = Math.min(menu.x, window.innerWidth - 270)
const y = Math.min(menu.y, window.innerHeight - (menu.items.length * 34 + 60)) const y = Math.min(menu.y, window.innerHeight - (menu.items.length * 34 + 60))
return ( return (
<div className="ctx" ref={ref} style={{ left: x, top: y }}> <div className="ctx-menu" ref={ref} style={{ left: x, top: y }}>
{menu.note && <div className="ctx-note">{menu.note}</div>} {menu.note && <div className="ctx-note">{menu.note}</div>}
{menu.items.map((it, i) => it.sep ? <div key={i} className="ctx-sep" /> : ( {menu.items.map((it, i) => it.sep ? <div key={i} className="ctx-sep" /> : (
<div key={i} className={'ctx-item' + (it.primary ? ' primary' : '') + (i === hi ? ' hi' : '')} <div key={i} className={'ctx-item' + (it.primary ? ' primary' : '') + (i === hi ? ' hi' : '')}

View File

@@ -417,7 +417,11 @@ body {
.term-ta::placeholder { color:var(--fg-3); } .term-ta::placeholder { color:var(--fg-3); }
/* context menu */ /* context menu */
.ctx { position:fixed; z-index:80; background:#23272d; border:1px solid var(--border-2); border-radius:9px; padding:5px; min-width:248px; box-shadow:0 16px 44px rgba(0,0,0,.5); } /* The floating context menu. Its own class (not bare `.ctx`) so this
position:fixed rule can never collide with the `.tree-row.ctx` / `.git-row.ctx`
highlight class — that collision pulled the highlighted row out of flow and
made the row beneath it appear to vanish while the menu was open. */
.ctx-menu { position:fixed; z-index:80; background:#23272d; border:1px solid var(--border-2); border-radius:9px; padding:5px; min-width:248px; box-shadow:0 16px 44px rgba(0,0,0,.5); }
.ctx-item { display:flex; align-items:center; gap:10px; padding:7px 10px; border-radius:6px; cursor:pointer; font-size:12.5px; color:var(--fg-1); } .ctx-item { display:flex; align-items:center; gap:10px; padding:7px 10px; border-radius:6px; cursor:pointer; font-size:12.5px; color:var(--fg-1); }
.ctx-item:hover, .ctx-item.hi { background:var(--accent-soft); color:var(--fg-0); } .ctx-item:hover, .ctx-item.hi { background:var(--accent-soft); color:var(--fg-0); }
.ctx-item .kc { margin-left:auto; font-family:var(--mono); font-size:10.5px; color:var(--fg-3); } .ctx-item .kc { margin-left:auto; font-family:var(--mono); font-size:10.5px; color:var(--fg-3); }