add new Context Menu for file Explorer

fix blocking UI
when select the file in Status also select in the file History
This commit is contained in:
Christoph Brandau
2026-07-02 16:24:38 +02:00
parent 794680a696
commit e3df75cc38
11 changed files with 399 additions and 75 deletions
+58 -1
View File
@@ -17,6 +17,7 @@
FileVideo,
Folder,
FolderOpen,
ExternalLink,
Terminal,
} from "@lucide/svelte";
import { languageIconForPath } from "../languageIcons";
@@ -34,6 +35,7 @@
onExpandAllFolders: () => void;
onCollapseAllFolders: () => void;
onSelectNode: (node: ExplorerNode) => void;
onOpenFile: (node: ExplorerNode) => void;
}
let {
@@ -47,8 +49,13 @@
onExpandAllFolders = () => {},
onCollapseAllFolders = () => {},
onSelectNode = () => {},
onOpenFile = () => {},
}: Props = $props();
let contextNode = $state<ExplorerNode | null>(null);
let contextMenuX = $state(0);
let contextMenuY = $state(0);
function mergeExplorerStatus(current: FileStatusKind | null, next: FileStatusKind | null): FileStatusKind | null {
if (!next) return current;
if (!current) return next;
@@ -154,12 +161,39 @@
return "text";
}
function openFileContextMenu(event: MouseEvent, node: ExplorerNode) {
if (node.kind !== "file") return;
event.preventDefault();
event.stopPropagation();
contextNode = node;
contextMenuX = Math.max(8, Math.min(event.clientX + 2, window.innerWidth - 192));
contextMenuY = Math.max(8, Math.min(event.clientY + 2, window.innerHeight - 56));
}
function closeFileContextMenu() {
contextNode = null;
}
function openContextFile() {
const node = contextNode;
if (!node || node.kind !== "file") return;
closeFileContextMenu();
onOpenFile(node);
}
function handleWindowKeydown(event: KeyboardEvent) {
if (event.key === "Escape") closeFileContextMenu();
}
let explorerTree = $derived(buildExplorerTree(repoFiles));
let visibleNodes = $derived(flattenExplorerTree(explorerTree, expandedExplorerPaths));
let hasFolders = $derived(explorerTree.some((node) => node.kind === "folder"));
</script>
<section class="panel grid grid-rows-[auto_1fr] overflow-hidden" aria-label="File explorer">
<svelte:window on:click={closeFileContextMenu} on:keydown={handleWindowKeydown} on:contextmenu|capture={closeFileContextMenu} />
<section class="panel explorer-panel grid grid-rows-[auto_1fr] overflow-hidden" aria-label="File explorer">
<div class="section-head">
<div>
<span class="eyebrow">Explorer</span>
@@ -264,6 +298,7 @@
class="explorer-select"
type="button"
onclick={() => onSelectNode(node)}
oncontextmenu={(event) => openFileContextMenu(event, node)}
disabled={isBusy}
title={`Show history for ${node.path}`}
>
@@ -279,4 +314,26 @@
{/each}
</div>
{/if}
</section>
{#if contextNode}
<div
class="explorer-context-menu"
style={`left: ${contextMenuX}px; top: ${contextMenuY}px;`}
role="menu"
tabindex="-1"
aria-label={`Actions for ${contextNode.path}`}
>
<button
type="button"
role="menuitem"
onclick={openContextFile}
disabled={contextNode.status === "deleted"}
title={contextNode.status === "deleted" ? "Deleted files cannot be revealed in Explorer" : "Reveal this file in Explorer"}
>
<ExternalLink size={14} aria-hidden="true" />
Open in Explorer
</button>
</div>
{/if}