Prose
The reading type. Wrap a document, CMS rich text, rendered Markdown or plain JSX, and its bare headings, lists, quotes, code and tables are typeset on Koala's tokens, with one size prop.
Installation#
Usage#
import { Prose } from "@/components/ui/prose"
export function Article({ html }: { html: string }) {
return <Prose size="lg" dangerouslySetInnerHTML={{ __html: html }} />
}Sizes#
The size picks the type and the rhythm together. sm is the 14px body of the product UI (a comment, a task description, what a RichTextEditor wrote); md is docs and release notes; lg is long-form reading at 17px, for an article at a ~42rem measure.
Rich text from a CMS#
A CMS, a Markdown renderer or a Tiptap export hands you a string of bare HTML. Set it on Prose and it is typeset as it is: no class to add to the content.
Elements#
Ordered lists carry tabular markers, inline code keeps the global chip, a pre is a muted block that scrolls on its own, a table scrolls inside the column instead of the page, and a picture gets the corner radius and the image outline. Media take a wider step than copy, so they read as breaks.
Components inside#
Prose styles bare elements. An anchor or image that carries a class is a component, so it keeps its own look: a Link or a Button dropped into the copy is never underlined or restyled.
As child#
Pass asChild to put the styling on your own element, an article or a section, instead of a wrapping div.
<Prose asChild size="lg">
<article>
<h2>Tokens over values</h2>
<p>A card does not know it is twelve pixels of radius; it knows it uses the surface radius.</p>
</article>
</Prose>