fix(cloud): picker empty state says 'Nothing else to open' or 'No cloud workspaces yet' (design-squad on #594)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Neil
2026-11-13 00:43:12 -08:00
co-authored by Claude
parent 8a31cba9f1
commit a96d20d04a
4 changed files with 37 additions and 26 deletions
@@ -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 () => {
@@ -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(<PickerEmptyState reason={{ kind: 'none' }} onCreate={onCreate} />)
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(<PickerEmptyState reason={{ kind: 'all-in-sidebar' }} onCreate={vi.fn()} />)
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(<PickerEmptyState reason={{ kind: 'search' }} onCreate={vi.fn()} />)
expect(screen.getByText('Nothing matches your search')).toBeTruthy()
expect(screen.queryByRole('button')).toBeNull()
@@ -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({
<div className="flex flex-col items-center gap-1 px-6 py-8 text-center">
<p className="text-sm font-medium text-foreground">{title}</p>
<p className="max-w-sm text-xs text-muted-foreground">{body}</p>
{reason.kind === 'none' && onCreate ? (
<Button type="button" size="sm" className="mt-3" onClick={onCreate}>
{(reason.kind === 'none' || reason.kind === 'all-in-sidebar') && onCreate ? (
// Primary when there are none at all; secondary when everything is already in the sidebar.
<Button
type="button"
size="sm"
variant={reason.kind === 'none' ? 'default' : 'outline'}
className="mt-3"
onClick={onCreate}
>
<Cloud className="size-3.5" />
{t('components.cloudWorkspaces.newCloudWorkspace', 'New cloud workspace')}
</Button>
+5 -5
View File
@@ -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": {