fix(desktop): one weight and one gap for transcript scaffolding

The scaffold rows shared a colour but not a weight: tool summaries and the
ticker rendered medium against the reply's normal-weight prose, which read
as emphasis on the quietest lines in the column.

Spacing had the matching problem. The block-gap rule listed which *pairs* of
blocks qualified, so the live status line — neither tool, thinking, nor
prose — fell through every branch onto its own half-size margin. And because
a streaming turn is sealed into several bubbles as it goes but rehydrates
into fewer, two blocks are siblings inside one bubble or split across two
depending on when you look; the flex gap between bubbles is half the block
gap, so the rhythm tightened and relaxed as a turn settled. Cover every
top-level block with one rule, keep prose-to-prose on paragraph rhythm, and
top the between-bubble gap up to match.
This commit is contained in:
Brooklyn Nicholson
2026-07-27 19:35:04 -05:00
parent 46df6ca705
commit 7a10e48e2f
3 changed files with 21 additions and 12 deletions
@@ -234,7 +234,7 @@ export const StreamStallIndicator: FC = () => {
}
return (
<StatusRow className="mt-1.5" data-slot="aui_stream-stall" label={hint || 'Hermes is thinking'}>
<StatusRow data-slot="aui_stream-stall" label={hint || 'Hermes is thinking'}>
<span aria-hidden="true" className="dither inline-block size-3 rounded-[2px] text-midground/80 animate-pulse" />
{hint && <HintText>{hint}</HintText>}
<ActivityTimerText seconds={elapsed} />
@@ -13,7 +13,7 @@ import { DisclosureRow } from '@/components/chat/disclosure-row'
* different kinds of line for what is one kind of thing.
*/
export const SCAFFOLD_LABEL_CLASS =
'text-[length:var(--conversation-tool-font-size)] font-medium leading-(--conversation-line-height) text-(--conversation-scaffold-text)'
'text-[length:var(--conversation-tool-font-size)] leading-(--conversation-line-height) text-(--conversation-scaffold-text)'
/** Durations, counts and diff stats trailing a scaffold label. */
export const SCAFFOLD_META_CLASS = 'shrink-0 text-[0.625rem] tabular-nums text-(--conversation-scaffold-meta)'
+19 -10
View File
@@ -1501,24 +1501,33 @@ text-* variant utilities. */ .btn-arc {
/* Conversation block rhythm. assistant-ui renders each range as a direct child
of the message content with no per-part wrapper, so adjacency rules cover
every pairing — first block needs no reset, nested tool rows are untouched.
Two tiers: scaffolding (tool / thinking) gets a roomy block gap so it reads
as separate from the reply; consecutive prose collapses to a tight paragraph
rhythm so split-out text parts don't look like a big gap. */
/* Scaffolding adjacent to anything → roomy block gap. */
One gap between top-level blocks, whatever they are. Spelling out which
*pairs* qualified meant the live status line (not tool, thinking or prose)
fell through every branch and carried its own half-size margin instead. */
[data-slot='aui_assistant-message-content']
> :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure'])
+ :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure'], .aui-md),
[data-slot='aui_assistant-message-content']
> .aui-md
+ :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure']) {
> :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure'], [data-slot='aui_stream-stall'], .aui-md)
+ :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure'], [data-slot='aui_stream-stall'], .aui-md) {
margin-top: var(--turn-block-gap);
}
/* Prose ↔ prose → tight paragraph rhythm, matching in-block paragraph spacing. */
/* Except prose ↔ prose: one reading column that happens to arrive as several
parts, so it keeps the in-block paragraph rhythm. Same specificity as the
rule above and deliberately after it. */
[data-slot='aui_assistant-message-content'] > .aui-md + .aui-md {
margin-top: var(--paragraph-gap);
}
/* A streaming turn is sealed into several assistant bubbles as it goes
(`message.interim`) and rehydrates into fewer, so the same two blocks are
sometimes siblings inside one bubble and sometimes split across two. The
flex gap between bubbles is the turn gap — half the block gap — which made
the rhythm visibly tighten and then relax as a turn settled. Top it up so
the column ticks at one interval either way. */
[data-slot='aui_turn-pair'] > [data-slot='aui_assistant-message-root'] + [data-slot='aui_assistant-message-root'] {
margin-top: calc(var(--turn-block-gap) - var(--conversation-turn-gap));
}
/* Message action bars — flat icon hits with default dim; only the hovered/focused control is full-strength. */
[data-slot='aui_msg-actions'] button {
border: 0;