From a96d20d04a6287cbb79cec3a32d3794a1bd22c18 Mon Sep 17 00:00:00 2001 From: Neil Date: Thu, 12 Nov 2026 21:46:57 -0800 Subject: [PATCH] fix(cloud): picker empty state says 'Nothing else to open' or 'No cloud workspaces yet' (design-squad on #594) Co-Authored-By: Claude --- .../CloudWorkspacePicker.test.tsx | 5 ++-- .../CloudWorkspacesStates.test.tsx | 20 +++++++++---- .../CloudWorkspacesStates.tsx | 28 +++++++++++-------- src/renderer/src/i18n/locales/en.json | 10 +++---- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/renderer/src/components/cloud-workspaces/CloudWorkspacePicker.test.tsx b/src/renderer/src/components/cloud-workspaces/CloudWorkspacePicker.test.tsx index 039c509cca8..fd68b8aac9e 100644 --- a/src/renderer/src/components/cloud-workspaces/CloudWorkspacePicker.test.tsx +++ b/src/renderer/src/components/cloud-workspaces/CloudWorkspacePicker.test.tsx @@ -124,12 +124,11 @@ describe('Open cloud workspace…', () => { expect(getCloudWorkspacePickerRequest()).not.toBeNull() }) - it('with everything in the sidebar, says so instead of inviting a first workspace', async () => { + it('with everything in the sidebar, says there is nothing else to open', async () => { listResult = { ok: true, value: [MINE] } renderPicker() act(() => openCloudWorkspacePicker()) - expect(await screen.findByText('Your cloud workspaces are already in the sidebar')).toBeTruthy() - expect(screen.queryByRole('button', { name: 'New cloud workspace' })).toBeNull() + expect(await screen.findByText('Nothing else to open')).toBeTruthy() }) it('a list that could not be read offers Try again', async () => { diff --git a/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.test.tsx b/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.test.tsx index f4fcede68bb..7e269c0155d 100644 --- a/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.test.tsx +++ b/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.test.tsx @@ -58,19 +58,27 @@ it('at the running limit, Show cloud workspaces opens the picker on your running closeCloudWorkspacePicker() }) -it('with none at all, invites the first cloud workspace with one button (JA-30)', () => { +it('with none at all, says so and offers New cloud workspace as the primary action', () => { const onCreate = vi.fn() render() - expect(screen.getByText('Start your first cloud workspace')).toBeTruthy() + expect(screen.getByText('No cloud workspaces yet')).toBeTruthy() + expect(screen.getByText('Start one and it shows up in your sidebar.')).toBeTruthy() fireEvent.click(screen.getByRole('button', { name: 'New cloud workspace' })) expect(onCreate).toHaveBeenCalledTimes(1) }) -it('every other empty list keeps its own copy and offers no create button', () => { +it('with everything in the sidebar, says there is nothing else and keeps a secondary New', () => { render() - expect(screen.getByText('Your cloud workspaces are already in the sidebar')).toBeTruthy() - expect(screen.queryByRole('button')).toBeNull() - cleanup() + expect(screen.getByText('Nothing else to open')).toBeTruthy() + expect( + screen.getByText('Every cloud workspace you can open is already in your sidebar.') + ).toBeTruthy() + expect( + screen.getByRole('button', { name: 'New cloud workspace' }).getAttribute('data-variant') + ).toBe('outline') +}) + +it('a search with no match keeps its own copy and offers no create button', () => { render() expect(screen.getByText('Nothing matches your search')).toBeTruthy() expect(screen.queryByRole('button')).toBeNull() diff --git a/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.tsx b/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.tsx index e2a7dff424d..f9f2e52ef2b 100644 --- a/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.tsx +++ b/src/renderer/src/components/cloud-workspaces/CloudWorkspacesStates.tsx @@ -104,7 +104,7 @@ export function PickerEmptyState({ onCreate }: { reason: PickerEmptyReason - /** Offered only when there are none at all: start one. */ + /** Start one: primary with none at all, secondary when all are in the sidebar. */ onCreate?: () => void }): React.JSX.Element { const t = useTranslate() @@ -128,13 +128,10 @@ export function PickerEmptyState({ ] case 'all-in-sidebar': return [ + t('components.cloudWorkspaces.picker.emptyNothingElseTitle', 'Nothing else to open'), t( - 'components.cloudWorkspaces.picker.emptyAllInSidebarTitle', - 'Your cloud workspaces are already in the sidebar' - ), - t( - 'components.cloudWorkspaces.picker.emptyAllInSidebarBody', - 'Workspaces teammates share, and ones you start on another computer, show up here.' + 'components.cloudWorkspaces.picker.emptyNothingElseBody', + 'Every cloud workspace you can open is already in your sidebar.' ) ] case 'none-running': @@ -159,10 +156,10 @@ export function PickerEmptyState({ ] case 'none': return [ - t('components.cloudWorkspaces.emptyFirstTitle', 'Start your first cloud workspace'), + t('components.cloudWorkspaces.picker.emptyNoneTitle', 'No cloud workspaces yet'), t( - 'components.cloudWorkspaces.emptyStartBody', - 'It runs in a sandbox, so your agents keep working even when this computer is off.' + 'components.cloudWorkspaces.picker.emptyNoneBody', + 'Start one and it shows up in your sidebar.' ) ] } @@ -171,8 +168,15 @@ export function PickerEmptyState({

{title}

{body}

- {reason.kind === 'none' && onCreate ? ( - diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 53b9a0f04d0..1ebfffab42d 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -24484,8 +24484,6 @@ }, "cloudWorkspaces": { "newCloudWorkspace": "New cloud workspace", - "emptyStartBody": "It runs in a sandbox, so your agents keep working even when this computer is off.", - "emptyFirstTitle": "Start your first cloud workspace", "picker": { "title": "Open cloud workspace", "description": "Cloud workspaces that aren’t in your sidebar: shared by teammates, or started on another computer.", @@ -24501,8 +24499,6 @@ "inSidebarNote_other": "{{count}} more are already in your sidebar.", "emptySearchTitle": "Nothing matches your search", "emptySearchBody": "Try a title, repository, branch, owner or W-number.", - "emptyAllInSidebarTitle": "Your cloud workspaces are already in the sidebar", - "emptyAllInSidebarBody": "Workspaces teammates share, and ones you start on another computer, show up here.", "emptyRunningTitle": "None of yours are running", "emptyRunningBody": "Teammates’ running workspaces can count toward the limit too. Try again in a moment.", "emptyTeammateTitle": "{{name}} has no cloud workspaces you can see", @@ -24514,7 +24510,11 @@ "sharedWorkspace": "shared workspace", "teammate": "teammate", "orcaCloud": "orca cloud" - } + }, + "emptyNothingElseTitle": "Nothing else to open", + "emptyNothingElseBody": "Every cloud workspace you can open is already in your sidebar.", + "emptyNoneTitle": "No cloud workspaces yet", + "emptyNoneBody": "Start one and it shows up in your sidebar." } }, "worktreeCreation": {