Prose
Prose.Root is a div that sets the type and spacing of rendered markdown or MDX: headings, paragraphs, lists and block quotes, drawn from the prose contract tokens. Wrap a docs page or an article in it, or the text of a chat message.
On this page
<Prose.Root>
<h2>Release notes</h2>
<p>This release adds a prose token group.</p>
<ul>
<li>Headings take their size from the prose tokens.</li>
</ul>
</Prose.Root>
Release notes
This release adds a prose token group. Every gap below follows the density.
- Headings take their size from the prose tokens.
- Lists indent by one step.
Upgrading
Nothing to change. Pages that set their own spacing keep it.
Quotes keep a rule at their start edge.
Server Components can import it from @tounsoo/todae/prose. The MDX pages of this site are set in it.
Type
Body text draws at prose.font.size. The default refs font.size.3. The custom property is --todae-prose-font-size.
Each heading level has its own size token. prose.h1.font.size refs font.size.6. prose.h2.font.size refs font.size.5. prose.h3.font.size refs font.size.4. prose.h4.font.size refs font.size.3. prose.h5.font.size refs font.size.3. prose.h6.font.size refs font.size.2. The custom properties are --todae-prose-h1-font-size, --todae-prose-h2-font-size, --todae-prose-h3-font-size, --todae-prose-h4-font-size, --todae-prose-h5-font-size and --todae-prose-h6-font-size.
A theme or a ThemeProvider override sets these paths. That changes Prose only. It does not change other uses of the same font.size step.
Spacing
Each child sits prose.gap below the one before it. A heading sits prose.heading.space-before below anything but a heading, and whatever follows a heading, another heading included, sits prose.heading.space-after below it. The first child and the last touch the edges of Prose.Root, so a card or a message bubble holds it with even padding. These spaces replace the margins of a Todae component that is a child, such as CodeBlock.Root, Separator.Root or Text.Root.
These gaps and prose.list.item-gap read density tokens, so they follow data-density as Stack.Root does.
Where the styles stop
Prose.Root styles h1 to h6, p, ul, ol, li and blockquote when every element between them and the root is one of these. Any other element, such as a div, table or pre, is where its styles stop: it is still spaced as a child, but what it holds keeps its own type. A list with a role, such as Stack.Root as="ul" or Tree.Root, keeps its own indent and the space between its items.
A class on one of those elements wins over the type Prose.Root sets, so <Text.Root as="h2" variant="label"> inside it keeps the label role's size.
Map markdown onto Todae
Prose.Root styles block text. Inline code, code blocks, links, rules and tables come from Todae's own components, which you hand to your markdown renderer. With MDX:
const components = {
// MDX passes its wrapper a `components` prop, so don't spread the props onto the div.
wrapper: ({ children }) => <Prose.Root>{children}</Prose.Root>,
a: Link.Root,
code: Code.Root,
pre: CodeBlock.Root,
hr: Separator.Root,
kbd: Kbd.Root,
table: Table.Root,
thead: Table.Head,
tbody: Table.Body,
tr: Table.Row,
th: Table.HeaderCell,
td: Table.Cell,
};
Prose.Root sets no typeface and no page background; Todae leaves both to the product. To set them from Todae's tokens:
:root {
font-family: var(--todae-text-font-family);
color: var(--todae-color-fg-default);
background: var(--todae-color-bg-canvas);
}
Accessible composition
Todae handles: Style only. Every element keeps its own role, so headings stay in the page outline.
You supply: Heading levels that fit the page outline. A chat message or a card inside a page usually starts below the page's own headings, so map the markdown's top level onto h3 or lower in your renderer.
Watch for: A heading level picked for its size; pick the level for the outline and change the size through the prose tokens. A block quote used only to indent text.
When to use
When: Text you render from markdown or MDX, where you don't write each element as a component: docs pages, articles, help text, chat messages.
When not: Interface text you write yourself → Text and Stack. A code block or a table on its own → Code or Table.
Props
| Name | Type | Description |
|---|