Richtext Array
The string-parsing sibling of InlineArray. Accepts a literal text fragment — [1, 2, 3], {a, b}, [[3,6],[1,4]] — and renders the matching inline chip without the caller having to tokenise the payload first.
Useful when the source data already arrives as a string: MDX prose, lesson narration, LLM output, or any rich-text runtime where the array is already in literal form. Pair with InlineArray when the source is already typed.
The chip Array, 4 elements: 3, 6, 1, 4.3614 flows with prose at the surrounding baseline.
Installation
npx shadcn@latest add https://craftbits.dev/r/richtext-array.jsonUsage
import { RichtextArray } from "@craft-bits/core";
<p>
Push <RichtextArray text="[1, 2, 3]" /> onto the frontier.
</p>Cascade cells in for a staged reveal:
<RichtextArray text="[1, 2, 3, 4]" animate baseDelay={0.2} />A 2D literal nests row-strips:
<RichtextArray text="[[3,6],[1,4],[8,10]]" tone="success" />An empty set renders the placeholder glyph at the inline baseline:
<RichtextArray text="{}" tone="muted" />Understanding the component
- One parser, three shapes. A leading
[[switches to the 2D branch; a leading{is a set (with the empty-set glyph fallback); anything else parses as a 1D array. Bad tokens drop out viaNumber.isNaNinstead of throwing, so a malformed fragment still renders the surrounding chip. - Inline sizing. The outer span is
h: 1.55emwithalign-middle,tabular-nums, and a mono font so digits stay column-aligned and the chip's baseline matches the surrounding line of text. - Tone via CSS variables.
tonepicks acb-*semantic var (accent/success/warning/danger/muted); the border, fill, and ink all derive from that one variable viacolor-mix(…)so the chip themes correctly under light and dark mode. - Cascade reveal. When
animateis set, each cell pops in viaSPRINGS.snapwith a delay ofbaseDelay + i * 0.04for 1D andbaseDelay + ri * 0.08 + ci * 0.04for 2D — the same sweep shape AlgoFlashcards used to land cells under staged prose. - Reduced motion. When
prefers-reduced-motion: reduceis set, the cell transition collapses toduration: 0— cells snap in regardless ofanimate.
Variants
A static literal — no animation:
<p>
Sort <RichtextArray text="[5, 2, 8, 1]" /> by ascending key.
</p>A 2D literal in the warning palette:
<RichtextArray text="[[1,2],[3,4]]" tone="warning" />The empty-set state:
<RichtextArray text="{}" tone="muted" />A cascade-in reveal with a base delay so the chip lands after the prose around it:
<RichtextArray text="[10, 20, 30, 40]" animate baseDelay={0.3} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | required | Literal text fragment to parse. |
tone | RichtextArrayTone | "accent" | Resting tone — accent, success, warning, danger, muted. |
animate | boolean | false | Cascade cells in via fade-and-pop. |
baseDelay | number | 0 | Base delay (seconds) added to every cell's stagger. |
transition | Transition | SPRINGS.snap | Override the cell transition. |
emptyPlaceholder | string | "{ }" | Glyph for the empty-set state. |
className | string | — | Merged onto the root via cn(). |
Accessibility
- The outer element is
role="img"with a hidden summary likeArray, 3 elements: 1, 2, 3.(or2D array, 3 rows.) so screen readers hear the chip's contents instead of reading each digit in isolation. - Each chip carries
data-state(array/set/2d/empty) anddata-toneso consumer apps can hook custom styles or assistive tooling. - The 2D comma separator is
aria-hiddenbecause the summary already conveys the row structure. - Color is never the only signal — every shape still renders its digits, and the empty-set state ships an explicit
aria-label="Empty set". - Motion respects
prefers-reduced-motion: reduce— cells snap in regardless ofanimate.
Credits
- Extracted from:
algoflashcards(src/platform/ui/richtext-array.tsx). The source parsed three literal shapes (1D array, set, 2D array) into bordered emerald chips using a hardcodedtrack-emeraldpalette and aSPRING.snappycascade. The library version keeps the parser branches and the cascade math but swaps the emerald palette for thecb-*tone system, pulls the spring intoSPRINGS.snap, exposesbaseDelayas a prop so callers can land the chip under staged prose, and lifts the cell renderer into a sharedCellso 1D and 2D code paths share the same animation contract.