Array Cells
A horizontal row of equal-size labelled cells — the foundational primitive for any array-based DSA visualization. Each cell can be styled per-index (highlight / visited / dimmed), labelled above with its index, and tagged below with one or more pointer labels (L, R, mid, …).
Array, 8 cells, 2 pointers.
3
7
10
17
23
29
42
54
Customize
Shape
8
md
Static markers
0
4
Playback
600 ms
Installation
npx shadcn@latest add https://craftbits.dev/r/array-cells.jsonUsage
import { ArrayCells } from "@craft-bits/core";
<ArrayCells
values={[3, 8, 12, 17, 24, 31, 42, 55]}
showIndices
pointers={[
{ index: 0, label: "L", tone: "success" },
{ index: 7, label: "R", tone: "error" },
]}
cellStyles={{ 3: "highlight" }}
/>Drive cell state from your own algorithm reducer — the component is pure render:
<ArrayCells
values={arr}
pointers={[
{ index: left, label: "L", tone: "success" },
{ index: right, label: "R", tone: "error" },
{ index: mid, label: "mid", tone: "accent" },
]}
cellStyles={Object.fromEntries(
visited.map((i) => [i, "visited"] as const),
)}
/>Understanding the component
- A column per cell. Each cell is a vertical
flexstack — index label on top, the cell box in the middle, and a pointer-label row underneath. The pointer row reserves space even when empty so the cell-box baseline doesn't jump as pointers move across the array. - Responsive cell width. Cell width is
clamp(min, calc((100% - totalGaps) / N), ideal)— cells render atcellSizeon wide viewports but shrink to ~60% on narrow ones. Never overflows iPhone-sized screens; never expands past the ideal grid. - Style states.
cellStylesmaps an index to one of four visual states:highlight(accent ring + tinted fill),visited(muted "done" look),dimmed(30% opacity), ordefault(resting look). - Pointers carry tone. Each pointer has a semantic
tonethat drives both the pointer label color and the matching cell's ring. The first pointer on a cell wins the ring color; subsequent pointers stack as additional labels. - Pointer transitions. Labels are wrapped in
AnimatePresencewithmode="popLayout"so moving a pointer between cells animates a fade-and-slide.initial={false}skips the mount-time stagger. - Reduced motion. When
prefers-reduced-motion: reduceis set, the transition collapses toduration: 0— pointer state changes snap instead of springing.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
values | (string | number)[] | required | Values rendered inside each cell, left → right. |
showIndices | boolean | false | Render numeric indices above each cell. |
pointers | { index, label, tone? }[] | [] | Pointer labels rendered beneath cells. |
cellStyles | Record<number, ArrayCellStyle> | {} | Per-cell state — default, highlight, visited, dimmed. |
cellSize | number | 44 | Ideal pixel size of each cell. |
compact | boolean | false | Tighter row, smaller cells, smaller labels. |
className | string | — | Merged onto the outer <div>. |
Accessibility
- The outer element is
role="group"with anaria-labelannouncing the array length. - Each cell carries a
data-stateattribute (default/highlight/visited/dimmed) so consumer apps can hook custom styles or assistive tooling. - Indices are decorative —
aria-hidden="true"so screen readers don't read out0 3 1 8 2 12 …. - Color is never the only signal: highlighted cells get a ring (not just a fill), pointer labels carry text (
L,R,mid), anddimmedcells drop their opacity — three orthogonal cues for colorblind users. - Pointer label motion respects
prefers-reduced-motion: reduce.
Credits
- Extracted from:
algoflashcards(src/lessons/primitives/viz/ArrayCells.tsx). The original supported tap-to-select and per-cell hex overrides for lesson-specific theming; the library extract narrows the API to semantic tones + style states so the same component drops into any DSA viz unchanged.