Usage
streaming, unfinished Markdown is completed before it is parsed, and only the block that is still growing redraws.
children is the Markdown source. labels is the copy Markdown cannot carry, passed once:
| Markdown | Rendered as |
|---|---|
# to ###### | Text with the heading element for the level, in the roles in RESPONSE_HEADING_TYPES |
| Paragraph | Text p |
**bold**, _italic_, ~~deleted~~ | strong, em, del, at body emphasis weight at most |
`code` | Text code in a subtle chip |
| Bulleted and numbered lists, nested | TypographyList and TypographyItem; an ordered list keeps its start number |
| Table | Table in an inline Scrollable named by labels.table; :-- and --: align cells to start and end |
| Fenced code | CodeBlock, with the fence's language |
| Block quote | A quote bar on the inline start edge, paragraphs in the subtle foreground |
--- | Separator |
| Link | Link; see below |
Reference link ([text][ref], [ref][], [ref]) | Link, resolved from a definition anywhere in the source |
Footnote ([^id], [^id]: text) | A superscript number linking to a numbered list in a named section after the last block |
| Image | The alt text. The image is never loaded |
| Raw HTML | Shown as text |
http, https, irc, ircs, mailto, xmpp, plus tel:), name no protocol other than http, https, mailto or tel (the ones Link opens with a native anchor, so a router adapter never reads irc: or xmpp: as an in-app path), and pass the design system's safe-URL check. A target that fails either is drawn as its text, with no anchor. Absolute web targets open in a new tab with rel="noopener noreferrer" and announce labels.newTab; phone, mail, relative and fragment targets stay in the tab.
The source is parsed once as a whole, then drawn block by block. Reference-style links and footnotes reach across blocks, and models usually write their definitions last, so Response reads the definitions from the whole syntax tree, wherever they sit, and gives each block what it uses:
[ref]: https://…) anywhere in the source is taken out of its block and put in front of every block that uses its label, so a block only changes when a definition it uses changes. The first definition of a label wins.labels.footnotes, each with a link back to its first reference named by labels.footnoteBack. A footnote definition may have several paragraphs; indent the later ones.[^1] and [text][ref] show as written until the definition arrives, then resolve.streaming, the source is repaired before parsing: an unclosed **, `, link, or code fence is closed. Without it the source is taken as written, so a finished response is never rewritten. The source is split into the top-level blocks of its syntax tree and each is memoized under a key that is the offset of its first line, so a reply of fifty paragraphs redraws one while its last paragraph grows. A fenced block, and a loose list with its fences and paragraphs, stay in one block.
components merges element renderers over the defaults. Pass a stable object (module-level or memoized): a new object every render redraws every block.
size={ResponseSize.Compact}: paragraphs and lists, and the links in them, then use Body Medium (13px over 18px), the size of the Reasoning trigger. Headings, tables and code keep their own roles.