diff --git a/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx b/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx index e3af7f426..ddb11435c 100644 --- a/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx +++ b/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx @@ -287,9 +287,10 @@ function openRunTargetPicker(container: HTMLElement): void { } function findRunTargetItem(label: string): HTMLElement | undefined { - return [...document.body.querySelectorAll('[cmdk-item]')].find((item) => - item.textContent?.includes(label) - ) + // Why: "Add host" is a pinned footer button (mirrors the Project combobox), not a cmdk row. + return [ + ...document.body.querySelectorAll('[cmdk-item], [data-run-target-add-host]') + ].find((item) => item.textContent?.includes(label)) } let current: { container: HTMLDivElement; root: Root } | null = null diff --git a/src/renderer/src/components/NewWorkspaceComposerCard.tsx b/src/renderer/src/components/NewWorkspaceComposerCard.tsx index 02542787f..062714ff6 100644 --- a/src/renderer/src/components/NewWorkspaceComposerCard.tsx +++ b/src/renderer/src/components/NewWorkspaceComposerCard.tsx @@ -13,6 +13,7 @@ import { CornerDownLeft, FolderPlus, LoaderCircle, + Monitor, PlugZap, Plus, Settings2, @@ -26,7 +27,7 @@ import { CommandList, CommandSeparator } from '@/components/ui/command' -import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { SettingsSwitch } from '@/components/settings/SettingsFormControls' import type RepoCombobox from '@/components/repo/RepoCombobox' @@ -71,6 +72,7 @@ import type { ReadyProjectHostSetupOption } from '@/lib/project-host-setup-options' import type { WorkspaceCreateErrorDisplay } from '@/lib/workspace-create-error-format' +import { LOCAL_EXECUTION_HOST_ID, type ExecutionHostId } from '../../../shared/execution-host' import type { SshConnectionStatus } from '../../../shared/ssh-types' import type { TaskSourceContext } from '../../../shared/task-source-context' import type { RuntimeStatus } from '../../../shared/runtime-types' @@ -355,6 +357,12 @@ function HostPathTooltip({ path }: { path: string }): React.JSX.Element { ) } +// Why: the local machine isn't a server — give it a monitor glyph so it reads as "this computer". +function HostRowIcon({ hostId }: { hostId: ExecutionHostId }): React.JSX.Element { + const Icon = hostId === LOCAL_EXECUTION_HOST_ID ? Monitor : Server + return +} + function WorkspaceRunTargetCombobox({ hostOptions, hostValue, @@ -501,7 +509,7 @@ function WorkspaceRunTargetCombobox({ ) : selectedHost ? ( - + {selectedHost.label} ) : ( @@ -534,7 +542,7 @@ function WorkspaceRunTargetCombobox({ onSelect={() => handleHostSelect(option.id)} onPointerEnter={closeSubmenus} onFocus={closeSubmenus} - className="items-center gap-2 px-3 py-2" + className="items-center gap-2 px-3 py-1.5" > - +
{option.label}
@@ -564,7 +572,7 @@ function WorkspaceRunTargetCombobox({ onSelect={() => {}} onPointerEnter={closeSubmenus} onFocus={closeSubmenus} - className="items-center gap-2 px-3 py-2" + className="items-center gap-2 px-3 py-1.5" >
@@ -576,7 +584,7 @@ function WorkspaceRunTargetCombobox({ ) : option.attention ? ( ) : ( - + )}
{option.label}
@@ -626,10 +634,10 @@ function WorkspaceRunTargetCombobox({ ))} ) : null} - {/* Why: separate the host list from the environment/add-host actions below, mirroring - the divider above the not-connected group so the two action rows read as their own - section rather than trailing the hosts. */} - {readyHostOptions.length > 0 || needsSetupHostOptions.length > 0 ? ( + {/* Why: separate the host list from the per-workspace-env row; the "Add host" action + is pinned below the list with its own border, so it needs no separator here. */} + {recipes.length > 0 && + (readyHostOptions.length > 0 || needsSetupHostOptions.length > 0) ? ( ) : null} {recipes.length > 0 ? ( @@ -641,7 +649,7 @@ function WorkspaceRunTargetCombobox({ onSelect={openVmRecipesSubmenu} onPointerEnter={openVmRecipesSubmenu} onFocus={openVmRecipesSubmenu} - className="items-center gap-2 px-3 py-2" + className="items-center gap-2 px-3 py-1.5" > handleRecipeSelect(recipe.id)} - className="items-center gap-2 px-3 py-2" + className="items-center gap-2 px-3 py-1.5" > ) : null} + + {/* Why: pin "Add host" below the scrollable list — mirrors the Project combobox's + "Add a new project" footer so it keeps a compact single-row height and one clean + divider instead of a taller in-list row above the popover edge. */} +
- - + + {/* Why: pin an empty value so cmdk doesn't auto-highlight the first row on open — matches the recipes submenu, which leaves nothing highlighted by default. */} @@ -731,7 +739,7 @@ function WorkspaceRunTargetCombobox({
@@ -752,7 +760,7 @@ function WorkspaceRunTargetCombobox({
@@ -774,7 +782,7 @@ function WorkspaceRunTargetCombobox({ - +
diff --git a/src/renderer/src/components/new-workspace/ProjectCombobox.tsx b/src/renderer/src/components/new-workspace/ProjectCombobox.tsx index 232d99190..f1dcea89f 100644 --- a/src/renderer/src/components/new-workspace/ProjectCombobox.tsx +++ b/src/renderer/src/components/new-workspace/ProjectCombobox.tsx @@ -199,7 +199,7 @@ export default function ProjectCombobox({ key={option.id} value={option.id} onSelect={() => handleSelect(option.id)} - className="items-center gap-2 px-3 py-2" + className="items-center gap-2 px-3 py-1.5" > @@ -1508,7 +1508,9 @@ export default function SmartWorkspaceNameField({ }} placeholder={placeholder} disabled={disabled} - className="h-9 pl-8 text-sm" + // Why: match the project/run-on comboboxes' solid `bg-background` — the input's + // default transparent fill made it read a different color on light mode. + className="h-9 bg-background pl-8 text-sm" /> )}