Rizz
2026-08-25 15:56:51 -07:00
committed by ss-dev-00
parent e297547c93
commit 67ebd54748
4 changed files with 40 additions and 7 deletions

View File

@@ -52,10 +52,13 @@ export function CompactMessageSummary({
const { goChannel } = useAppNavigation();
const { openProfilePanel } = useProfilePanel();
const isCompactPreview = variant === "compactPreview";
const shouldClampBubble = !isCompactPreview;
const isConversation = variant === "conversation";
// Focus mode is a reading view, so sent messages remain fully visible there.
// The default activity surface keeps the compact clamp.
const shouldClampBubble = !isCompactPreview && !isConversation;
const [bubbleRef, hasBubbleOverflow] =
useTranscriptBubbleOverflow(shouldClampBubble);
const canOpenMessage = shouldClampBubble && messageLink !== null;
const canOpenMessage = !isCompactPreview && messageLink !== null;
const mutedTone = compactSummaryTone();
const avatarClassName = cn(
"mr-2 mt-1 shrink-0",
@@ -135,7 +138,12 @@ export function CompactMessageSummary({
testId="transcript-agent-sent-avatar"
/>
)}
<div className="flex min-w-0 flex-1 flex-col items-start gap-1">
<div
className={cn(
"flex min-w-0 flex-1 flex-col items-start gap-1",
isConversation && "pr-9",
)}
>
<div
className={cn(
"w-full min-w-0 rounded-2xl border px-3 py-2",

View File

@@ -65,6 +65,11 @@ test("conversation renders the prompt as a filled right-aligned bubble with an a
const bubble = row.querySelector(".rounded-2xl");
assert.ok(bubble, "the prompt should match Buzz's chat-bubble radius");
assert.match(bubble.className, /bg-muted\/60/);
assert.doesNotMatch(
bubble.className,
/(?<!\/)bg-muted(?!\/)/,
"sender prompts use the lighter muted tint rather than the agent-send surface",
);
assert.match(bubble.className, /px-4/);
assert.match(bubble.className, /py-2(?!\.)/);
assert.match(

View File

@@ -391,12 +391,28 @@ test("the same relay post outside a work block keeps its message bubble", async
await router.load();
const view = render(createElement(RouterProvider, { router }));
const bubble = view.container.querySelector(
'[data-testid="transcript-tool-message-preview"]',
);
assert.ok(
view.container.querySelector(
'[data-testid="transcript-tool-message-preview"]',
),
bubble,
"outside a block a posted message is a destination the reader can open — the bubble stays",
);
assert.doesNotMatch(
bubble.className,
/max-h-36/,
"focus mode shows the full sent message rather than clamping it",
);
assert.match(
bubble.parentElement.className,
/pr-9/,
"the left-side bubble keeps exterior space mirroring the sender avatar gutter",
);
assert.match(
bubble.className,
/(?<!\/)bg-muted(?!\/)/,
"agent sends use the stronger muted surface to distinguish them from sender prompts",
);
});
test("the rail glyph is chosen by kind, and prose kinds share the speech bubble", async () => {

View File

@@ -206,7 +206,11 @@ export function UserMessageBubble({
{hasBubbleOverflow ? (
<span className="pointer-events-none absolute inset-x-0 bottom-0 h-8 rounded-b-2xl bg-linear-to-b from-transparent to-background" />
) : null}
{messageLink ? <MessageLinkHoverCue /> : null}
{messageLink ? (
<MessageLinkHoverCue
className={isConversation ? "top-3" : undefined}
/>
) : null}
</div>
{isConversation && footer ? (
// Timestamp/context row is chrome, not content: focus mode keeps it