cleanup(web): give adding a Workspace one route
Both Workspace surfaces offered "Open local folder…" and "Create a new
workspace" for one outcome. The browse occupant already carries its own
New folder affordance, so picking a directory covered creating one; the
name dialog only added a second vocabulary and a create target the
operator could neither see nor choose.
The surviving entry is named after the outcome — "Add workspace…" — and a
menu now appears only where there is something to choose between: with no
Workspace listed (the add-only sidebar header, or an empty hero list) the
anchor gesture raises the directory flow directly instead of a one-row
popover. An empty list counts as final only after the list baseline lands,
and a composition with no directory-flow occupant hides the sidebar button
rather than offering a dead one.
WorkspaceCreateFlow becomes WorkspacePickFlow (createOnly -> addOnly) and
the injected createWorkspace narrows to { path }. The host's
workspace.create({ name }) branch and `dsh web --workspace-root` lost their
last product consumer; both are marked at the call site for a follow-up.
This commit is contained in:
@@ -500,23 +500,26 @@ describe('WorkspaceBrowser', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('rail create-workspace toggles the create-only picker in place, without expanding', () => {
|
||||
it('rail add-workspace raises the directory flow in place, with no menu and no expansion', () => {
|
||||
const expandSidebar = vi.fn()
|
||||
mount({ wide: false, expandSidebar, useWorkspaces: hook(workspaceState([workspace('alpha', [])])) })
|
||||
fireEvent.click(screen.getByRole('button', { name: '创建工作区' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: '添加工作区' }))
|
||||
expect(expandSidebar).not.toHaveBeenCalled()
|
||||
// createOnly: existing workspaces are not listed, only the create actions.
|
||||
// Adding is the header's only action, so the gesture IS that action: no
|
||||
// one-row popover, and existing workspaces stay in the tree below.
|
||||
expect(screen.queryByRole('menu')).toBeNull()
|
||||
expect(screen.queryByRole('menuitem', { name: 'alpha' })).toBeNull()
|
||||
expect(screen.getByRole('menuitem', { name: '打开本地文件夹…' })).toBeTruthy()
|
||||
// Toggle: open and close in place.
|
||||
fireEvent.click(screen.getByRole('button', { name: '创建工作区' }))
|
||||
expect(screen.queryByRole('menu')).toBeNull()
|
||||
expect(screen.getByTestId('directory-flow')).toBeTruthy()
|
||||
})
|
||||
|
||||
// Escape closes the picker through its own onClose.
|
||||
fireEvent.click(screen.getByRole('button', { name: '创建工作区' }))
|
||||
expect(screen.getByRole('menu')).toBeTruthy()
|
||||
fireEvent.keyDown(document, { key: 'Escape' })
|
||||
expect(screen.queryByRole('menu')).toBeNull()
|
||||
it('hides the add button when no directory-flow occupant is composed', () => {
|
||||
mount({
|
||||
useWorkspaces: hook(workspaceState([workspace('alpha', [])])),
|
||||
useDirectoryFlow: bindSnapshotSelector({ getSnapshot: () => false, subscribe: () => () => {} }),
|
||||
})
|
||||
// Nothing to add with, so the header offers no dead button.
|
||||
expect(screen.queryByRole('button', { name: '添加工作区' })).toBeNull()
|
||||
expect(screen.getByText('alpha')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('drag reorder reports the anchor to insertSessionBefore and skips no-op drops', () => {
|
||||
|
||||
Reference in New Issue
Block a user