qwen-code/packages/web-shell/client/components/sidebar/WorkspaceSection.module.css
Shaojin Wen 2709d1fccd
feat(web-shell): surface worktree isolation in the new-session empty state (#7365)
* feat(web-shell): surface worktree isolation in the new-session empty state

The worktree-isolated session entry was buried in the sidebar git-branch
pill dropdown, making it hard to discover. Add a visible toggle to the
chat empty state — the de-facto new-session page — that reuses the
existing pending-worktree state machine and lazy session creation, so no
SDK or daemon changes are needed. Enabling it shows the pending badge
with a cancel affordance; the first prompt then creates the session in an
isolated worktree. The toggle is offered only when the target workspace
is trusted and is a git repository, mirroring the sidebar entry gating.

Also simplify the sidebar git pill: drop the now-redundant "New worktree
task" item and make the pill open the changes view directly instead of a
single-item dropdown.

* chore: add PR verification screenshots for the worktree toggle

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(web-shell): capture the new-session empty state in the visuals suite

The worktree toggle lives in the new-session empty state, and every visuals
scenario navigates to /session/:id via gotoSession — so the suite had never
rendered the empty state at all, and the before/after preview reported "no
screenshot changes" for this PR despite the new UI.

Add a `gotoNewSession` harness helper (primes the theme, lands on `/`, asserts
the theme took effect; no replay to settle) and a `worktree empty state`
scenario using the git-ready workspace this PR already made mockable
(`gitStatus` + the /workspaces/:cwd/git route). It captures both states — the
offered toggle and, after clicking, the pending-worktree badge with its cancel
affordance — and asserts the swap, so a regression fails an assertion rather
than only differing in the screenshot. All four captures are byte-stable
across runs (0% pixel diff).

The helper also closes the structural gap: any future empty-state work
(onboarding copy, first-run affordances) now has a way into the preview.

* refactor(web-shell): drop dead worktree session opt; click-test git chip (#7365)

* fix(web-shell): address review feedback on worktree toggle (#7365)

- Move focus to cancel button on toggle enable and back on cancel (a11y)
- Include branch name in git-pill button aria-label (a11y)
- Replace hardcoded flush() ticks with vi.waitFor() in test helper
- Move git-repo mock default from afterEach to beforeEach
- Add test: sidebar New chat clears pending worktree intent

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: wenshao <wenshao@example.com>
Co-authored-by: Qwen Code Autofix <qwen-code-autofix@users.noreply.github.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
2026-07-21 07:38:33 +00:00

148 lines
2.8 KiB
CSS

.section {
display: flex;
flex-direction: column;
}
.headerRow {
display: flex;
align-items: center;
width: 100%;
border-radius: 6px;
transition: background 0.1s;
}
.header {
min-width: 0;
flex: 1 1 auto;
display: flex;
align-items: center;
gap: 6px;
padding: 6px 8px;
border: none;
background: transparent;
color: var(--sidebar-foreground);
font-size: 14px;
text-align: left;
cursor: pointer;
}
.headerRow:hover,
.headerRow:focus-within {
background: var(--sidebar-accent);
}
.headerDisabled {
opacity: 0.5;
}
.headerDisabled .header {
cursor: not-allowed;
}
.headerContent {
min-width: 0;
flex: 1 1 auto;
display: flex;
align-items: center;
gap: 6px;
}
.chevron {
display: inline-flex;
align-items: center;
}
.folderIcon {
display: block;
}
.chevronOpen {
color: var(--sidebar-foreground);
}
.name {
min-width: 0;
flex: 0 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.badge {
font-size: 10px;
color: var(--muted-foreground);
background: var(--sidebar-accent);
padding: 1px 5px;
border-radius: 4px;
}
/* Live git chip in the folder header — icon-only (the chip's `compact` form): a
status dot on the branch icon conveys dirty / conflict / in-progress at a
glance, while the branch name + ahead/behind live in the hover tooltip.
Rendered as a sibling of the header button (buttons can't nest), kept snug
after the folder name. The chip is a fixed 28px box, so the pill grows only to
carry the spare width to the hover actions on the right. */
.gitPill {
display: inline-flex;
flex: 1 1 auto;
min-width: 0;
padding: 0;
border: none;
background: none;
font: inherit;
color: inherit;
text-align: inherit;
cursor: pointer;
}
/* With a chip present, let the pill — not the folder name — own the spare width,
so the icon sits right after the name and the hover actions stay pinned to the
right edge. Without a chip the header keeps growing as before. */
.headerRow:has(.gitPill) .header {
flex-grow: 0;
}
/* Trusted sessions use the sidebar's shared row with its own left indent;
read-only rows apply the same indent below. */
.sessions {
display: flex;
flex-direction: column;
gap: 4px;
margin-bottom: 12px;
}
.empty {
padding: 4px 8px 4px 26px;
font-size: 13px;
color: var(--muted-foreground);
}
.error {
padding: 4px 8px 4px 26px;
color: var(--error-color);
font-size: 13px;
}
.sessionItemReadOnly {
display: flex;
align-items: center;
gap: 6px;
margin-left: 26px;
padding: 4px 8px;
border-radius: 8px;
color: var(--muted-foreground);
cursor: default;
}
.sessionName {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sessionTime {
flex: 0 0 auto;
font-size: 10px;
color: var(--muted-foreground);
}