qwen-code/packages/web-shell/client/components/ChatPane.module.css
Shaojin Wen 55b2886909
fix(web-shell): split-view pane fixes (remove "current" badge, clear composer on send) (#6454)
* fix(web-shell): remove meaningless "current" badge from split-view panes

In the split view every pane is an equal, independently interactive session (its own DaemonSessionProvider, SSE, transcript, and approvals), so tagging one pane as the workspace's "current" session carried no operational meaning. It only leaked a single-view concept into a peer-of-equals layout and reliably prompted "what is this?" questions from users. Panes are already identified by their titles.

Drop the isCurrent badge and its border highlight from ChatPane, and stop passing isCurrent from SplitView. The sidebar and session overview keep their "current" indicators, which are legitimate "you are here" navigation. currentSessionId is retained only to seed the initial pane.

* fix(web-shell): clear the split-view composer on send, not at turn end

A split-view pane kept the just-sent text sitting in its composer until the whole turn finished. handleSubmit committed the draft on the sendPrompt promise resolving, but that promise resolves via waitForAcceptedPromptCompletion (turn end), not at admission. Switch to the onAdmitted hook so the composer clears the moment the daemon accepts the prompt, matching the main view. A prompt rejected before admission still preserves the draft and surfaces the error.

* fix(web-shell): pass commitAccepted directly as onAdmitted; cover admit-then-fail

Review follow-up:
- commitAccepted is already `() => void`, so pass it directly as the onAdmitted option instead of wrapping it in a redundant `() => commitAccepted?.()` closure.
- Add a test for the turn failing after admission: the draft stays cleared (no second commit) and the error is still surfaced to onError.
2026-07-07 14:08:59 +00:00

88 lines
1.8 KiB
CSS

.pane {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
height: 100%;
background: var(--background);
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
}
.header {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-bottom: 1px solid var(--border);
background: color-mix(in srgb, var(--foreground) 3%, transparent);
flex: 0 0 auto;
}
/* Per-pane connection-loss indicator: each pane has its own daemon connection,
so a drop on one shouldn't silently leave stale messages with no signal. */
.connectionError {
flex: 0 0 auto;
padding: 6px 10px;
background: var(--warning-bg);
border-bottom: 1px solid var(--warning-border);
color: var(--warning-color);
font-size: 12px;
}
.connectionErrorText {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.title {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
font-weight: 600;
color: var(--foreground);
}
.closeButton {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border: none;
border-radius: 6px;
background: transparent;
color: var(--muted-foreground);
cursor: pointer;
}
.closeButton:hover {
color: var(--foreground);
background: color-mix(in srgb, var(--foreground) 8%, transparent);
}
/* The transcript takes the remaining height and scrolls independently per pane. */
.body {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.footer {
flex: 0 0 auto;
border-top: 1px solid var(--border);
padding: 8px;
position: relative;
}
.approval {
margin-bottom: 8px;
}