UI: flip bubble hierarchy — responses elevated, prompts recessed

Design direction: "Illuminated Transcript" — the AI response is the
primary artifact; user prompts are subordinate margin notes.

ChatMessage.vue:
- User bubble: ghosted background (rgba 3-4% opacity), muted text,
  thin near-invisible border. De-emphasized, recessed.
- Assistant bubble: left indigo accent border (2px), elevated shadow
  via --color-bubble-asst-shadow. Commands attention.
- Assistant role label: indigo (var(--color-primary)); user label muted.
- Removed old white-override content rules (no longer on dark bg).
- Thinking block: full border → left-only indigo accent bar (35% opacity),
  removed inner top border.

ChatView.vue:
- Streaming bubble: same left accent + shadow as assistant bubbles.
- Streaming role label: indigo to match ChatMessage.
- Thinking block in streaming: same treatment as ChatMessage.

theme.css:
- Added --color-bubble-user-bg/border/text for light + dark.
- Added --color-bubble-asst-shadow for light + dark.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Van Deusen
2026-03-10 15:02:39 -04:00
parent 4a3899d103
commit 5d9085d564
3 changed files with 26 additions and 27 deletions
+8
View File
@@ -38,6 +38,10 @@
--color-input-bar-text: #1a1a1a; --color-input-bar-text: #1a1a1a;
--color-input-bar-placeholder: rgba(0, 0, 0, 0.4); --color-input-bar-placeholder: rgba(0, 0, 0, 0.4);
--color-overlay: rgba(0, 0, 0, 0.45); --color-overlay: rgba(0, 0, 0, 0.45);
--color-bubble-user-bg: rgba(0, 0, 0, 0.04);
--color-bubble-user-border: rgba(0, 0, 0, 0.08);
--color-bubble-user-text: #555566;
--color-bubble-asst-shadow: 0 2px 16px rgba(99, 102, 241, 0.10), 0 1px 4px rgba(0, 0, 0, 0.06);
--radius-sm: 6px; --radius-sm: 6px;
--radius-md: 12px; --radius-md: 12px;
--radius-lg: 18px; --radius-lg: 18px;
@@ -85,6 +89,10 @@
--color-input-bar-text: #e4e4f0; --color-input-bar-text: #e4e4f0;
--color-input-bar-placeholder: rgba(228, 228, 240, 0.35); --color-input-bar-placeholder: rgba(228, 228, 240, 0.35);
--color-overlay: rgba(0, 0, 0, 0.65); --color-overlay: rgba(0, 0, 0, 0.65);
--color-bubble-user-bg: rgba(255, 255, 255, 0.03);
--color-bubble-user-border: rgba(255, 255, 255, 0.07);
--color-bubble-user-text: #5a5a72;
--color-bubble-asst-shadow: 0 4px 28px rgba(99, 102, 241, 0.14), 0 2px 8px rgba(0, 0, 0, 0.4);
} }
*, *,
+13 -23
View File
@@ -121,13 +121,19 @@ const timingParts = computed((): string[] => {
border-radius: 18px; border-radius: 18px;
} }
/* User prompts: recessed, muted — margin notes */
.role-user .message-bubble { .role-user .message-bubble {
background: linear-gradient(135deg, #6366f1, #4f46e5); background: var(--color-bubble-user-bg);
color: #fff; border: 1px solid var(--color-bubble-user-border);
color: var(--color-bubble-user-text);
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
} }
/* Assistant responses: elevated, lit — the primary text */
.role-assistant .message-bubble { .role-assistant .message-bubble {
background: var(--color-bg-card); background: var(--color-bg-card);
border-left: 2px solid var(--color-primary);
box-shadow: var(--color-bubble-asst-shadow);
border-bottom-left-radius: 4px; border-bottom-left-radius: 4px;
} }
@@ -144,16 +150,17 @@ const timingParts = computed((): string[] => {
letter-spacing: 0.03em; letter-spacing: 0.03em;
} }
.role-user .role-label { .role-user .role-label {
color: rgba(255, 255, 255, 0.7); color: var(--color-text-muted);
opacity: 0.6;
} }
.role-assistant .role-label { .role-assistant .role-label {
color: var(--color-text-muted); color: var(--color-primary);
} }
.thinking-block { .thinking-block {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
border: 1px solid var(--color-border); border-left: 2px solid rgba(129, 140, 248, 0.35);
border-radius: var(--radius-sm); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
overflow: hidden; overflow: hidden;
} }
.thinking-summary { .thinking-summary {
@@ -191,7 +198,6 @@ details[open] .thinking-summary::before {
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
background: var(--color-bg-secondary); background: var(--color-bg-secondary);
border-top: 1px solid var(--color-border);
} }
.message-content { .message-content {
font-size: 0.95rem; font-size: 0.95rem;
@@ -202,22 +208,6 @@ details[open] .thinking-summary::before {
margin-bottom: 0; margin-bottom: 0;
} }
/* User bubble content overrides for readability on primary bg */
.role-user .message-content :deep(a) {
color: rgba(255, 255, 255, 0.9);
text-decoration: underline;
}
.role-user .message-content :deep(code) {
background: rgba(255, 255, 255, 0.15);
color: #fff;
}
.role-user .message-content :deep(pre) {
background: rgba(0, 0, 0, 0.2);
}
.role-user .message-content :deep(blockquote) {
border-left-color: rgba(255, 255, 255, 0.4);
color: rgba(255, 255, 255, 0.85);
}
.message-actions { .message-actions {
display: flex; display: flex;
+5 -4
View File
@@ -1222,6 +1222,8 @@ onUnmounted(() => {
border-radius: 18px; border-radius: 18px;
border-bottom-left-radius: 4px; border-bottom-left-radius: 4px;
background: var(--color-bg-card); background: var(--color-bg-card);
border-left: 2px solid var(--color-primary);
box-shadow: var(--color-bubble-asst-shadow);
} }
.streaming-bubble .message-header { .streaming-bubble .message-header {
display: flex; display: flex;
@@ -1231,7 +1233,7 @@ onUnmounted(() => {
.streaming-bubble .role-label { .streaming-bubble .role-label {
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 600; font-weight: 600;
color: var(--color-text-muted); color: var(--color-primary);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.03em; letter-spacing: 0.03em;
} }
@@ -1258,8 +1260,8 @@ onUnmounted(() => {
} }
.thinking-block { .thinking-block {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
border: 1px solid var(--color-border); border-left: 2px solid rgba(129, 140, 248, 0.35);
border-radius: var(--radius-sm); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
overflow: hidden; overflow: hidden;
} }
.thinking-summary { .thinking-summary {
@@ -1297,7 +1299,6 @@ details[open] .thinking-summary::before {
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
background: var(--color-bg-secondary); background: var(--color-bg-secondary);
border-top: 1px solid var(--color-border);
} }
.streaming-status-dot { .streaming-status-dot {
display: inline-block; display: inline-block;