diff --git a/apps/desktop/src/electron/ElectronMenu.ts b/apps/desktop/src/electron/ElectronMenu.ts index 66b809b2ac7..005c86e0868 100644 --- a/apps/desktop/src/electron/ElectronMenu.ts +++ b/apps/desktop/src/electron/ElectronMenu.ts @@ -44,6 +44,12 @@ function normalizeContextMenuItems(source: readonly ContextMenuItem[]): ContextM continue; } + // Header items are decorative section labels for the web fallback only — + // Electron's native menu has no equivalent affordance, so we skip them. + if (sourceItem.header === true) { + continue; + } + const normalizedItem: ContextMenuItem = { id: sourceItem.id, label: sourceItem.label, diff --git a/apps/web/src/components/CommandPalette.logic.ts b/apps/web/src/components/CommandPalette.logic.ts index 4484232c2b8..982950be5e5 100644 --- a/apps/web/src/components/CommandPalette.logic.ts +++ b/apps/web/src/components/CommandPalette.logic.ts @@ -95,6 +95,7 @@ export function buildProjectActionItems(input: { valuePrefix: string; icon: (project: Project) => ReactNode; runProject: (project: Project) => Promise; + shortcutCommand?: KeybindingCommand; }): CommandPaletteActionItem[] { return input.projects.map((project) => ({ kind: "action", @@ -103,6 +104,7 @@ export function buildProjectActionItems(input: { title: project.name, description: project.cwd, icon: input.icon(project), + ...(input.shortcutCommand !== undefined ? { shortcutCommand: input.shortcutCommand } : {}), run: async () => { await input.runProject(project); }, diff --git a/apps/web/src/components/CommandPalette.tsx b/apps/web/src/components/CommandPalette.tsx index 0cb889ff1cb..ebfc260ca43 100644 --- a/apps/web/src/components/CommandPalette.tsx +++ b/apps/web/src/components/CommandPalette.tsx @@ -647,6 +647,7 @@ function OpenCommandPaletteDialog() { buildProjectActionItems({ projects, valuePrefix: "new-thread-in", + shortcutCommand: "chat.new", icon: (project) => ( = repository_path: "Group by repository path", separate: "Keep separate", }; +const SIDEBAR_ICON_ACTION_BUTTON_CLASS = + "inline-flex h-6 min-w-6 cursor-pointer items-center justify-center rounded-md px-[calc(--spacing(1)-1px)] text-muted-foreground/60 hover:text-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring"; function clampSidebarThreadPreviewCount(value: number): SidebarThreadPreviewCount { return Math.min( @@ -635,7 +637,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP data-thread-selection-safe data-testid={`thread-archive-confirm-${thread.id}`} aria-label={`Confirm archive ${thread.title}`} - className="absolute top-1/2 right-1 inline-flex h-5 -translate-y-1/2 cursor-pointer items-center rounded-full bg-destructive/12 px-2 text-[10px] font-medium text-destructive transition-colors hover:bg-destructive/18 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-destructive/40" + className="absolute top-1/2 right-1 inline-flex h-5 -translate-y-1/2 cursor-pointer items-center rounded-md bg-destructive/12 px-2 text-[10px] font-medium text-destructive transition-colors hover:bg-destructive/18 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-destructive/40" onPointerDown={stopPropagationOnPointerDown} onClick={handleConfirmArchiveClick} > @@ -643,13 +645,13 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP ) : !isThreadRunning ? ( appSettingsConfirmThreadArchive ? ( -
+