Chat foundations
What @sdxc/ui/chat is for, the structure and scrolling rules its parts share, and every variable it reads.
A conversation: a scrolling log, one row per turn with avatar, header and footer, bubbles, inline markers and attachment cards.
Everything is server HTML; following the latest message and opening an attachment are mixins you add where the thread updates live.
import "@sdxc/ui/theme.css";
import { … } from "@sdxc/ui/chat";When to reach for it
- A support inbox, a team thread or any log of messages between people.
- An assistant's conversation, with streamed replies and Markdown inside the bubbles.
- Any feed where new entries arrive at the bottom and a reader may scroll back.
Shared ideas
- Structure
Messageis anarticleon a grid filled bydata-slot; the namespace renders no headings. - Container layout
Message,MessageScrollerandAttachmentreflow on their own width, wherever the thread sits. - DirectionBubble corners and margins are logical properties, so end-aligned bubbles mirror in RTL.
- Scrolling
messageFollowkeeps the log at the latest turn until the reader scrolls away; instant under reduced motion. - AccessibilityThe log is
role="log"witharia-busyfor streaming; reactions are a labelled group. - MarkdownWrap a reply in
<Typeset preset="chat">: 15px on a 1.5 line.
CSS variables
Every custom property the namespace reads or declares, with its default and what it controls.
Reads the neutral and brand roles, danger for a failed bubble, and all five roles through Marker's color. The roles are documented on Theming.
Spacing and measure
None is declared in theme.css; set any of them on an ancestor of the thread.
| Variable | Default | What it controls |
|---|---|---|
--ui-message-gap | 0.75rem | Gap between a message's avatar and its header and content. |
--ui-message-row-gap | 0.25rem | Gap between a message's header, content and footer. |
--ui-message-content-max-size | 36rem | Widest a turn's content grows, its reading measure. |
--ui-message-group-gap | 0.125rem | Gap between consecutive messages in a Message.Group. |
--ui-marker-gap | 0.375rem | Gap between a Marker's icon, label and rules. |
--ui-message-scroller-anchor-offset | 0px | Space a scrolled-to turn leaves above itself, to clear an overlay. |
--ui-separator-thickness | 1px | Thickness of a separator Marker's rules. |
Shape and elevation
Read through @sdxc/u's rounded() and shadow(); each default is the fallback an app overrides by declaring the variable.
| Variable | Default | What it controls |
|---|---|---|
--ui-radius-xs | 0.125rem | The tight corner where a bubble meets its sender's edge or a grouped neighbour. |
--ui-radius-md | 0.375rem | Corners of a Marker and an attachment's media. |
--ui-radius-lg | 0.5rem | Corners of the scroller's frame and an attachment card. |
--ui-radius-xl | 0.75rem | Corners of a bubble. |
--ui-shadow-md | 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) | Elevation of the jump-to-latest button. |
--ui-bg | var(--ui-neutral-bg-tint, Canvas) | Opaque fill of the jump-to-latest button. |
Set by the components
| Variable | Default | What it controls |
|---|---|---|
--ui-bubble-reactions-justify | set by Bubble from align | Which side a bubble's reactions row lines up with. |