mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-11 12:12:19 -10:00
* feat(web-shell): add grouped message deletion with durable history updates * fix(web-shell): repair message deletion CI contracts * docs(serve): index message deletion protocol routes * fix(web-shell): harden grouped deletion recovery and export build * fix(web-shell): allow selecting all message groups for deletion * test(cli): observe hook cancellation rejection before waiting --------- Co-authored-by: 钉萁 <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]>
137 lines
3.9 KiB
CSS
137 lines
3.9 KiB
CSS
.row {
|
|
position: relative;
|
|
padding: 5px 0;
|
|
}
|
|
|
|
.toolGroupSpacing {
|
|
padding: 8px 0;
|
|
}
|
|
|
|
/*
|
|
* Anchored inside the message row rather than floating above it: the message
|
|
* list (`.list`) is `overflow-y: auto`, so a tooltip spilling outside the row
|
|
* box would be clipped or trigger a scrollbar. Staying within the row keeps it
|
|
* visible at the scroll edges. `pointer-events: none` lets clicks and inner
|
|
* hover interactions (tool expand, links) pass through.
|
|
*
|
|
* Anchored at the BOTTOM-right, and fully opaque. Both halves matter, and the
|
|
* position is the load-bearing one.
|
|
*
|
|
* At the top-right the chip's lower edge cuts horizontally through the first
|
|
* line of the message, and the first line of a wrapped block is the one that
|
|
* runs the full column width. It does not hide the last word so much as
|
|
* decapitate it: the chip removes a letter's ascender while its bowl stays
|
|
* visible below, so "finished." reads as "finisheu." -- the shape that kept
|
|
* being reported as a corrupted error message in web-shell previews. Making
|
|
* the background opaque alone does NOT fix that; it erases the faint remnant
|
|
* of the ascender and leaves the letter looking even more like a "u". Moving
|
|
* the chip off the text is what fixes it. The last line of a wrapped block is
|
|
* a ragged remainder, and rows carrying an action bar (the turn-error Copy
|
|
* button) leave that corner empty outright.
|
|
*
|
|
* Opacity still matters on its own: at 92% a glyph beneath any overlay bleeds
|
|
* through it, which reads as broken text rather than as a chip. `.chatTip` and
|
|
* `.copyButton` sit over content too (`.chatActions` pulls itself up by -24px)
|
|
* and carry the same fix. So does `.toolTimeTip` in SubAgentPanel.module.css,
|
|
* which mirrors this chip over a sub-tool line and had no `background` at all
|
|
* -- but only its background: that row cannot wrap and is about as tall as the
|
|
* chip, so it has no slack to move into. `visual-capture-contracts.test.ts`
|
|
* pins these, because no test reads this geometry: reverting the anchor or the
|
|
* background keeps every suite green.
|
|
*
|
|
* Overlap is now rare, not impossible -- a message whose last block is a
|
|
* full-width code block or table still gets the chip in its corner. Reserving
|
|
* space in flow was rejected: hover-time padding reflows the transcript, and a
|
|
* permanent float notch shrinks every code block that establishes its own
|
|
* formatting context.
|
|
*/
|
|
.tip {
|
|
position: absolute;
|
|
bottom: 2px;
|
|
right: 4px;
|
|
z-index: 5;
|
|
color: var(--muted-foreground);
|
|
background: var(--background);
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
padding: 1px 4px;
|
|
font-size: 11px;
|
|
line-height: 1.4;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity 0.12s ease;
|
|
}
|
|
|
|
.row:hover > .tip {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Chat mode: timestamp shown at bottom-right on hover */
|
|
.chatRow {
|
|
position: relative;
|
|
display: flex;
|
|
width: 100%;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.chatTip {
|
|
color: var(--muted-foreground);
|
|
background: var(--background);
|
|
border-radius: 4px;
|
|
padding: 1px 4px;
|
|
font-size: 11px;
|
|
line-height: 1.4;
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity 0.12s ease;
|
|
}
|
|
|
|
.chatActions {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
margin-top: -24px;
|
|
margin-right: 4px;
|
|
z-index: 5;
|
|
opacity: 0;
|
|
transition: opacity 0.12s ease;
|
|
}
|
|
|
|
.chatActions .chatTip {
|
|
opacity: 1;
|
|
}
|
|
|
|
.copyButton {
|
|
display: inline-flex;
|
|
width: 20px;
|
|
height: 20px;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: 5px;
|
|
background: var(--background);
|
|
color: var(--muted-foreground);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.copyButton:hover,
|
|
.copyButton:focus-visible {
|
|
color: var(--muted-foreground);
|
|
outline: none;
|
|
}
|
|
|
|
.copyButton svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
.chatRow:hover > .chatActions,
|
|
.chatRow:focus-within > .chatActions,
|
|
.chatActions[data-menu-open='true'] {
|
|
opacity: 1;
|
|
}
|