feat(app): always show the host picker with Add host on New workspace (#7580)

The Host field used to render only with two or more hosts, and Add host
only appeared on compact layouts. Single-host users had no sign that
Paseo can drive other machines from this screen. The field now always
renders and its menu always ends with Add host.
This commit is contained in:
Mohamed Boudra
2026-10-21 18:56:12 +07:00
committed by GitHub
parent 23c4df4818
commit 1d383519dd
2 changed files with 14 additions and 8 deletions
@@ -95,7 +95,7 @@ test.describe("New workspace entry points", () => {
}
});
test("the New Workspace screen hides the host selector when there is only one host", async ({
test("the New Workspace screen shows the host selector with Add host when there is only one host", async ({
page,
}) => {
const seeded: SeededWorkspace = await seedWorkspace({ repoPrefix: "entry-single-host-" });
@@ -120,7 +120,12 @@ test.describe("New workspace entry points", () => {
await expect(page.getByTestId("new-workspace-project-picker-trigger")).toBeVisible({
timeout: 30_000,
});
await expect(page.getByTestId("host-picker-trigger")).toHaveCount(0);
const hostTrigger = page.getByTestId("host-picker-trigger");
await expect(hostTrigger).toContainText("localhost", { timeout: 30_000 });
await hostTrigger.click();
await expect(page.getByTestId("new-workspace-host-picker-add-host")).toBeVisible();
await page.getByTestId("new-workspace-host-picker-add-host").click();
await expect(page).toHaveURL(/\/settings\/general\?addHost=/);
} finally {
await seeded.cleanup();
}
@@ -160,7 +160,8 @@ function useRefRenderOption(itemById: Map<string, PickerItem>, isPending: boolea
/**
* The New workspace setup fields, one trigger per field, each opening its picker. Compact: a stack
* of full-width fields with the label inside. Desktop: one meta row of badges. Either way, a field
* that does not apply to the selected project is left out, and Host only shows with a second host.
* that does not apply to the selected project is left out. Host always shows, even with one host, so
* its Add host action keeps multi-host discoverable.
*/
export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement {
const { t } = useTranslation();
@@ -170,7 +171,6 @@ export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement
const isolationPicker = useIsolationPicker(isolation, isPending);
const renderRefOption = useRefRenderOption(base.itemById, isPending);
const showHost = host.allHosts.length > 1;
const selectedHostLabel =
host.allHosts.find((h) => h.serverId === host.selectedServerId)?.label ?? "Host";
const selectedProject = project.selectedProject;
@@ -214,7 +214,7 @@ export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement
testID="new-workspace-project-picker-trigger"
/>
);
const hostField = showHost ? (
const hostField = (
<HostPicker
hosts={host.allHosts}
value={host.selectedServerId}
@@ -222,8 +222,9 @@ export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement
open={host.openState}
onOpenChange={host.onOpenChange}
anchorRef={host.anchorRef}
includeAddHost={isCompact}
includeAddHost
onAddHost={host.onAddHost}
addHostTestID="new-workspace-host-picker-add-host"
searchable={false}
title={t("newWorkspace.fields.host")}
desktopPlacement="bottom-start"
@@ -242,7 +243,7 @@ export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement
testID="host-picker-trigger"
/>
</HostPicker>
) : null;
);
const isolationField = isolation.canCreateWorktree ? (
<FieldTrigger
ref={isolation.anchorRef}
@@ -349,7 +350,7 @@ export function useNewWorkspaceForm(props: NewWorkspaceFormProps): ReactElement
return (
<View testID="new-workspace-ref-picker-row" style={styles.desktopRow} pointerEvents="box-none">
<View style={styles.desktopControl}>{projectField}</View>
{hostField ? <View style={styles.desktopControl}>{hostField}</View> : null}
<View style={styles.desktopControl}>{hostField}</View>
{isolationField ? <View style={styles.desktopControl}>{isolationField}</View> : null}
{baseField ? <View style={styles.desktopControl}>{baseField}</View> : null}
<View style={styles.launchSpacer} pointerEvents="none" />