/** * MessageBubble — a single chat message, tokenised and a11y-clean. * * Two complementary forms share one styled container: * * - **Bare bubble** (the common case for a message list that renders its own * author/time/reactions around each row): opt into the styling axes by passing * `variant` and/or `own` (plus `content` or a `children` snippet). No header or * labelled group is rendered — unless you also pass an `author` — so it nests * cleanly inside an already-labelled message row without a redundant landmark. * - **Self-contained card** (legacy form): pass `role` / `author` / `timestamp` * (and optionally the `reactions` / `actions` snippets) without the styling * axes. A header and a labelled `role="group"` (` ()`) are * rendered so assistive tech can announce who sent each message; `author` * falls back to a role label ("You" / "Assistant" / "System"). * * `variant` + `own` are the canonical styling axes. The legacy `role` prop sets * the header's role label and derives `variant`/`own` when those are not given. */ import type { Snippet } from 'svelte'; import type { ChatMessageRole } from '../../types-generic'; /** Visual tone: a peer message, an assistant message, or a centered notice. */ export type MessageBubbleVariant = 'default' | 'agent' | 'system'; export interface Props { /** Visual tone. Canonical styling axis. */ variant?: MessageBubbleVariant; /** Whether the current viewer authored this message — drives alignment + own-color. */ own?: boolean; /** * Legacy role. Prefer `variant` + `own`. Sets the header's role label and, * when `variant`/`own` are unset, derives them (user → own default, agent → * agent, system → system). */ role?: ChatMessageRole; /** Plain-text body. Ignored when a `children` snippet is provided. */ content?: string; /** Body snippet (takes precedence over `content`). */ children?: Snippet; /** Display name of the sender. When set, a header + labelled group render. */ author?: string; /** Message time; rendered in a `