@workerdeck/ui 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workerdeck/ui",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "description": "Styled agent-control component library for WorkerDeck: session panel, transcript with streaming, tool-call cards, permission prompts, session list, composer. Tailwind v4 + Base UI + cva. Pairs with the headless @workerdeck/react layer.",
6
6
  "license": "MIT",
@@ -38,9 +38,9 @@
38
38
  "streamdown": "^2.5.0",
39
39
  "tailwind-merge": "^3.6.0",
40
40
  "use-stick-to-bottom": "^1.1.6",
41
- "@workerdeck/client": "0.12.0",
42
- "@workerdeck/protocol": "0.12.0",
43
- "@workerdeck/react": "0.12.0"
41
+ "@workerdeck/react": "0.13.0",
42
+ "@workerdeck/client": "0.13.0",
43
+ "@workerdeck/protocol": "0.13.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "monaco-editor": "^0.56.0",
@@ -16,6 +16,7 @@ import { Spinner } from '../ui/Spinner.tsx'
16
16
  import { PromptArea } from '../prompt-area/prompt-area.tsx'
17
17
  import { usePromptAreaState } from '../prompt-area/use-prompt-area-state.ts'
18
18
  import { commandTrigger, mentionTrigger } from '../prompt-area/trigger-presets.ts'
19
+ import { useLines } from './transcript-variant.tsx'
19
20
  import type { TriggerSuggestion } from '../prompt-area/types.ts'
20
21
  import { cn } from '../../lib/utils.ts'
21
22
  import { formatBytes } from '../../lib/format.ts'
@@ -140,6 +141,9 @@ export function Composer({
140
141
  ref,
141
142
  }: ComposerProps) {
142
143
  const inline = layout === 'inline'
144
+ // The transcript's variant reaches here through the panel-wide context, so
145
+ // the composer matches the rows above it without a prop chain.
146
+ const lines = useLines()
143
147
  const { bind, plainText, isEmpty, clear, focus } = usePromptAreaState()
144
148
  const fileInput = useRef<HTMLInputElement>(null)
145
149
  const [dragging, setDragging] = useState(false)
@@ -378,9 +382,19 @@ export function Composer({
378
382
  pick(e.dataTransfer.files)
379
383
  }}
380
384
  className={cn(
381
- 'mx-auto w-full max-w-[var(--wd-content-max-w,48rem)] overflow-hidden rounded-lg border border-border bg-bg shadow-(--shadow-xs)',
382
- 'transition-colors focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30',
383
- dragging && 'border-ring ring-2 ring-ring/30',
385
+ 'mx-auto w-full max-w-[var(--wd-content-max-w,48rem)] overflow-hidden border border-border bg-bg',
386
+ 'transition-colors',
387
+ // VS Code's input: a flat, near-square box that gains a 1px accent
388
+ // border on focus. No radius worth the name, no shadow, no glow ring —
389
+ // an editor's chrome sits *in* the surface rather than floating above
390
+ // it, and the `lines` transcript above it has no rounded box either.
391
+ lines
392
+ ? 'rounded-sm focus-within:border-accent'
393
+ : cn(
394
+ 'rounded-lg shadow-(--shadow-xs)',
395
+ 'focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30',
396
+ ),
397
+ dragging && (lines ? 'border-accent' : 'border-ring ring-2 ring-ring/30'),
384
398
  disabled && 'opacity-60',
385
399
  )}>
386
400
  {/* Above the field, like the picture you are talking about should be. */}
@@ -445,13 +459,7 @@ export function Composer({
445
459
  <X className='size-3' />
446
460
  </button>
447
461
  </div>
448
- ) : (
449
- <div
450
- data-slot='composer-hint'
451
- className='mx-auto mt-1 w-full max-w-[var(--wd-content-max-w,48rem)] text-center text-label text-fg-4'>
452
- Enter to send · Shift+Enter for a new line
453
- </div>
454
- )}
462
+ ) : null}
455
463
  </div>
456
464
  )
457
465
  }
@@ -0,0 +1,97 @@
1
+ import { cn } from '../../lib/utils.ts'
2
+
3
+ /**
4
+ * The engine's own mark, monochrome.
5
+ *
6
+ * Inlined rather than depended on: the React package these come from
7
+ * (`@lobehub/icons`) pulls antd, `@lobehub/ui` and a second copy of
8
+ * lucide-react — an absurd amount of bundle for a few glyphs in a sidebar.
9
+ * These are paths from `@lobehub/icons-static-svg` (MIT, © LobeHub), already
10
+ * `fill="currentColor"` single-path marks, so they take the row's colour like
11
+ * any other glyph and need no light/dark variants.
12
+ *
13
+ * The marks are trademarks of their owners (Anthropic, OpenAI, Google,
14
+ * DeepSeek, Moonshot), used here only to identify which engine a session runs
15
+ * on.
16
+ *
17
+ * Codex is drawn as OpenAI: the session's engine *is* OpenAI's, and OpenAI's
18
+ * mark is the one a person recognises at 12px.
19
+ */
20
+ const PATHS: Record<string, { title: string; d: string }> = {
21
+ claude: {
22
+ title: 'Claude',
23
+ d: 'M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z',
24
+ },
25
+ codex: {
26
+ title: 'OpenAI',
27
+ d: 'M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z',
28
+ },
29
+ gemini: {
30
+ title: 'Gemini',
31
+ d: 'M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z',
32
+ },
33
+ deepseek: {
34
+ title: 'DeepSeek',
35
+ d: 'M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z',
36
+ },
37
+ moonshot: {
38
+ title: 'Moonshot',
39
+ d: 'M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z',
40
+ },
41
+ }
42
+
43
+ /**
44
+ * Which mark a session wears.
45
+ *
46
+ * The two first-party engines are named directly. A `provider` session is
47
+ * whatever the host wired up, so its *model* is the only thing that says whose
48
+ * it is — sniffed loosely on purpose (`gemini-2.5-pro`, `deepseek-chat`,
49
+ * `kimi-k2`), and falling through to no mark rather than guessing wrong.
50
+ */
51
+ export function engineMark(engine: string, model?: string): string | undefined {
52
+ if (engine === 'claude') return 'claude'
53
+ if (engine === 'codex') return 'codex'
54
+ const id = model?.toLowerCase() ?? ''
55
+ if (!id) return undefined
56
+ if (id.includes('gemini')) return 'gemini'
57
+ if (id.includes('deepseek')) return 'deepseek'
58
+ if (id.includes('moonshot') || id.includes('kimi')) return 'moonshot'
59
+ if (id.includes('claude')) return 'claude'
60
+ if (id.startsWith('gpt') || id.startsWith('o1') || id.startsWith('o3') || id.includes('openai')) {
61
+ return 'codex'
62
+ }
63
+ return undefined
64
+ }
65
+
66
+ export function EngineIcon({
67
+ engine,
68
+ model,
69
+ className,
70
+ }: {
71
+ engine: string
72
+ model?: string
73
+ className?: string
74
+ }) {
75
+ const mark = PATHS[engineMark(engine, model) ?? '']
76
+ // An engine this build has never heard of still gets a slot, so the second
77
+ // line doesn't reflow around a missing glyph.
78
+ if (!mark) {
79
+ return (
80
+ <span aria-hidden title={engine} className={cn('shrink-0 text-fg-3', className)}>
81
+ ·
82
+ </span>
83
+ )
84
+ }
85
+ return (
86
+ <svg
87
+ viewBox='0 0 24 24'
88
+ fill='currentColor'
89
+ fillRule='evenodd'
90
+ role='img'
91
+ aria-label={mark.title}
92
+ className={cn('size-3 shrink-0 text-fg-3', className)}>
93
+ <title>{mark.title}</title>
94
+ <path d={mark.d} />
95
+ </svg>
96
+ )
97
+ }
@@ -79,7 +79,10 @@ export function Loader({ label, startedAt, tokens, className }: LoaderProps) {
79
79
 
80
80
  return (
81
81
  <div data-slot='loader' className={cn('flex items-baseline gap-2', className)}>
82
- <LineGlyph className='text-accent'>{pulse}</LineGlyph>
82
+ {/* `lines` is monochrome: the terminal treatment earns its calm by
83
+ spending no colour on decoration, and a pulsing glyph is already the
84
+ loudest thing on a still page. `cards` keeps the brand accent. */}
85
+ <LineGlyph className={lines ? 'text-fg-3' : 'text-accent'}>{pulse}</LineGlyph>
83
86
  <span className='min-w-0 flex-1 text-body-sm leading-5 text-fg-3'>
84
87
  {verb}…{' '}
85
88
  {readings.length ? <span className='text-label text-fg-4'>({readings.join(' · ')})</span> : null}
@@ -9,9 +9,12 @@ export interface MessageProps extends HTMLAttributes<HTMLDivElement> {
9
9
  /**
10
10
  * One chat turn row.
11
11
  *
12
- * `cards`: user messages sit right in a bubble; assistant content is flat,
13
- * full-width (the AI-chat convention assistant output is the page, user input
14
- * is quoted).
12
+ * `cards`: user messages sit in a bubble, assistant content is flat and
13
+ * full-width. Both are **left-aligned**: the transcript is a log read top to
14
+ * bottom, and an editor-shaped host (a full-width session view beside a sessions
15
+ * rail) has no right edge to anchor to — a bubble drifting right in a 1600px
16
+ * column separates a prompt from the reply it produced. The bubble alone is
17
+ * enough to say who spoke.
15
18
  *
16
19
  * `lines`: both are left-aligned full-width line items behind a gutter glyph —
17
20
  * `❯` for what was typed, `●` for what the model said. No bubble: a prompt is
@@ -35,13 +38,13 @@ export function Message({ from, className, children, ...props }: MessageProps) {
35
38
  // inside it, and square-ish so it reads as a strip, not a bubble.
36
39
  from === 'user' && '-mx-1 rounded-sm bg-surface px-1',
37
40
  )
38
- : cn('flex-col gap-1', from === 'user' ? 'items-end' : 'items-start'),
41
+ : 'flex-col items-start gap-1',
39
42
  className,
40
43
  )}
41
44
  {...props}>
42
45
  {lines ? (
43
46
  <>
44
- <LineGlyph className={from === 'user' ? 'text-accent' : 'text-fg-3'}>
47
+ <LineGlyph className={from === 'user' ? 'text-fg-2' : 'text-fg-3'}>
45
48
  {from === 'user' ? '❯' : '●'}
46
49
  </LineGlyph>
47
50
  <div className='flex min-w-0 flex-1 flex-col gap-1'>{children}</div>
@@ -65,7 +68,8 @@ export function MessageContent({ className, ...props }: HTMLAttributes<HTMLDivEl
65
68
  : cn(
66
69
  'text-body-sm leading-6 text-fg-1',
67
70
  // Bubble treatment only within a user message row.
68
- 'in-data-[from=user]:max-w-[85%] in-data-[from=user]:rounded-lg in-data-[from=user]:rounded-br-sm',
71
+ // The tail points bottom-*left* now that the bubble is left-aligned.
72
+ 'in-data-[from=user]:max-w-[85%] in-data-[from=user]:rounded-lg in-data-[from=user]:rounded-bl-sm',
69
73
  'in-data-[from=user]:bg-accent-bg in-data-[from=user]:px-3 in-data-[from=user]:py-2',
70
74
  'in-data-[from=user]:whitespace-pre-wrap',
71
75
  'in-data-[from=assistant]:w-full',
@@ -182,7 +182,7 @@ export function QuestionPrompt({ request, onAnswer, onDismiss, className }: Ques
182
182
  return (
183
183
  <div key={index} className='flex flex-col'>
184
184
  <div className='flex items-baseline gap-2'>
185
- <LineGlyph className='text-info'>?</LineGlyph>
185
+ <LineGlyph className='text-fg-3'>?</LineGlyph>
186
186
  <span className='min-w-0 flex-1 text-body-sm leading-5 text-fg-1'>
187
187
  {q.header ? <span className='text-fg-4'>{q.header} · </span> : null}
188
188
  <span className='font-medium'>{q.question}</span>