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.

Preview

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.

Customize
Variant
body
Alignment
start

Installation

npx shadcn@latest add https://craftbits.dev/r/rich-paragraph.json

Usage

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

PropTypeDefaultDescription
variant'body' | 'lead''body'Visual variant. lead lifts the first paragraph.
align'start' | 'center' | 'end' | 'justify''start'Inline text alignment.
classNamestringMerged onto the root via cn().
childrenReactNodeParagraph 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-bg in both themes.
  • No motion — no prefers-reduced-motion fallback required.

Credits

  • Extracted from: terminal-dreams (src/components/ui/RichParagraph.tsx). The source detected string children and spliced them through a project-local RichText parser — useful for that codebase, but library-hostile (parser coupling, no forwardRef, 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 against cb-* tokens and picks the right text-wrap strategy for the variant.