RichParagraph
An editorial <p> primitive that consumes the cb-* typography tokens and chooses a sensible text-wrap strategy per variant. The body variant uses text-wrap: pretty for ragged-right body copy; the lead variant uses text-wrap: balance on a larger size for the opening paragraph of a section.
The dot product is the smallest brick in the stack. Projecting v onto a unit vector is a single dot product, and two vectors are orthogonal exactly when their dot product is zero.
Installation
npx shadcn@latest add https://craftbits.dev/r/rich-paragraph.jsonUsage
import { RichParagraph } from "@craft-bits/core";
<RichParagraph variant="lead">
The dot product is the smallest brick in the stack.
</RichParagraph>
<RichParagraph>
Projecting <strong>v</strong> onto a unit vector is a single dot product.
</RichParagraph>Prefer the subpath import when you only want this primitive:
import { RichParagraph } from "@craft-bits/core/text/rich-paragraph";Variants
Lift the opening paragraph with variant="lead":
<RichParagraph variant="lead">Opening sentence on cb-fg.</RichParagraph>Centre the paragraph:
<RichParagraph align="center">Centred body copy.</RichParagraph>Inline marks are ordinary children — drop <strong>, <em>, <code>, <a> directly, or compose with the RichElement* primitives for the fully tokenised vocabulary:
<RichParagraph>
Two vectors are <em>orthogonal</em> when their dot product is zero.
</RichParagraph>Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'body' | 'lead' | 'body' | Visual variant. lead lifts the first paragraph. |
align | 'start' | 'center' | 'end' | 'justify' | 'start' | Inline text alignment. |
className | string | — | Merged onto the root via cn(). |
children | ReactNode | — | Paragraph body. Inline marks are ordinary children. |
All other props are forwarded to the underlying <p> element.
Accessibility
- Pure typography — no interactive controls.
- Body text targets WCAG AA contrast (~4.5:1) against
--cb-bgin both themes. - No motion — no
prefers-reduced-motionfallback required.
Credits
- Extracted from:
terminal-dreams(src/components/ui/RichParagraph.tsx). The source detected string children and spliced them through a project-localRichTextparser — useful for that codebase, but library-hostile (parser coupling, noforwardRef, no className merge, no variants). The library version drops the parser branch entirely: inline composition is the caller's job, the component just paints the paragraph againstcb-*tokens and picks the righttext-wrapstrategy for the variant.