A flow-rhythm container — applies the .primitiv-flow context so every direct child gets density-scoped vertical spacing via a one-directional owl. Zero behaviour; renders a semantic element, composing the consumer's own element via asChild.
Registry-only
No headless primitive — this component ships only as a copied styled file, so there is no Headless mode. primitiv add prose installs it whichever mode you are reading.
Playground
Preview
Flow rhythm
A flow container spaces its direct children with a one-directional owl: each child gets margin above it, scaled to the density around it.
Nothing here sets a margin of its own — the rhythm comes from the context, so headings, paragraphs, lists and media all share one vertical scale.
Density is set by a data-density ancestor — the Context system, not a Prose prop.
Installation
npx primitiv add prose
pnpm dlx primitiv add prose
yarn dlx primitiv add prose
bunx primitiv add prose
Import
import{Prose}from"@/components/ui/prose";
No headless primitive — this one ships only as a copied styled surface, so primitiv add is the only way in, whichever mode you are reading.
Props
Generated from the copied file’s props type and contract.json. Never hand-maintained.
Prose
Extends HTMLDivElement — every native attribute of that element is accepted and forwarded.
Prop
Type
Default
Description
asChild
boolean
—
Render the single child element instead of a wrapping <div>, merging the
flow class onto it — e.g. <Prose asChild><article>...</article></Prose>.
measure
"false" | "true"
false
Caps the column at a comfortable reading line length (~68 characters) via --primitiv-prose-measure. Opt-in: a flow context is often a whole region containing grids and media, which a reading-width cap would break.
Styling contract
5 CSS custom properties on .primitiv-flow — mode-agnostic. These names are the stable surface; the values are not.
Prose renders a plain <div> with no semantics — it is a spacing context, so a screen reader reads straight through to the content. Use asChild to make it a real <article>/<section> when the region is a landmark.
Capping the line length with measure is itself an accessibility win: over-long lines are hard to track back to the next line, so a reading column helps low-vision and dyslexic readers.
It adds no interactive or ARIA surface; the meaning is entirely in the content it wraps.
Examples
Every example below reacts to the density control. Currently showing Styled mode.
Vertical rhythm
Wrap a run of content and every direct child gets vertical spacing from the context — no margin on the elements themselves. It is a one-directional owl (* + * { margin-block-start }), so the first child has no stray top margin, and the gaps scale with the nearest data-density. Change the density above and the whole rhythm shifts.
Flow rhythm
A flow container spaces its direct children with a one-directional owl: each child gets margin above it, scaled to the density around it.
Nothing here sets a margin of its own — the rhythm comes from the context, so headings, paragraphs, lists and media all share one vertical scale.
measure caps the column at a comfortable reading line length (~68 characters), which keeps long-form text scannable. It is opt-in: a flow context is often a whole region holding grids and media, and a reading-width cap would break those — so you add measure only on a genuine reading column.
Flow rhythm
A flow container spaces its direct children with a one-directional owl: each child gets margin above it, scaled to the density around it.
Nothing here sets a margin of its own — the rhythm comes from the context, so headings, paragraphs, lists and media all share one vertical scale.
import{Prose}from"@/components/ui/prose";<Prosemeasure><h3>A reading column</h3><p>{/* long-form text, capped at the measure */}</p></Prose>
As a semantic element
asChild renders your own element with the flow context applied — an <article> or <section> that also spaces its children — rather than wrapping one in an anonymous <div>. The rhythm still lands on the direct children of that element.
Flow rhythm
A flow container spaces its direct children with a one-directional owl: each child gets margin above it, scaled to the density around it.
Nothing here sets a margin of its own — the rhythm comes from the context, so headings, paragraphs, lists and media all share one vertical scale.