Vector Visualizer
A square SVG plane that renders N labelled 2D vectors from a tail point (default: the origin) to a head (x, y) in math coordinates (y points up). Each vector carries a semantic tone, and the whole set can be made draggable — the foundation primitive for any linear-algebra or vector-arithmetic demo.
Vector A: (3.0, 2.0), magnitude 3.6. Vector B: (-2.0, 3.0), magnitude 3.6. Vector C: (1.0, -3.0), magnitude 3.2.
Customize
Vectors
3
Display
Installation
npx shadcn@latest add https://craftbits.dev/r/vector-visualizer.jsonUsage
import { VectorVisualizer } from "@craft-bits/core";
<VectorVisualizer
vectors={[
{ x: 3, y: 2, label: "A", tone: "accent" },
{ x: -2, y: 3, label: "B", tone: "success" },
]}
/>Make it interactive — each arrow head becomes a drag handle. Pair interactive with onVectorsChange to receive the updated array:
const [vectors, setVectors] = useState<Vector2D[]>([
{ x: 3, y: 2, label: "A", tone: "accent" },
{ x: -2, y: 3, label: "B", tone: "success" },
]);
<VectorVisualizer
vectors={vectors}
interactive
onVectorsChange={setVectors}
/>Draw a vector that doesn't start at the origin by setting tail:
<VectorVisualizer
vectors={[
{ x: 2, y: 2, label: "u" },
{ x: 4, y: 3, tail: { x: 2, y: 2 }, label: "v" },
]}
/>Understanding the component
- Math-space coordinates, y points up. Vectors are passed in math space (positive y is up) and the component converts to SVG coordinates internally. The viewport is a square plane with the origin centered — width and height share the same
range. - Auto-derived scale. The visible domain
range(default[-5, 5]) feeds the px-per-unit scale. Changingsizerescales the SVG without changing the visible math span. - Five semantic tones.
default/accent/success/warning/errormap tovar(--cb-fg),var(--cb-accent),var(--cb-success),var(--cb-warning),var(--cb-error). Arrow markers are generated per tone in the SVG<defs>so every head matches its stroke. - Optional grid + axes.
showGridpaints integer-spaced gridlines invar(--cb-border-muted);showAxespaints x and y axes through the origin invar(--cb-fg-muted). Toggle either off for a clean canvas. - Drag affordance on the head. When
interactive, an invisible 32px-diameter circle on top of each arrow head acts as a WCAG-compliant hit target. Dragging projects the pointer through the SVG'sgetScreenCTM().inverse()so it tracks correctly under any transform; the head clamps torange. - Keyboard parity. The drag handle is a
role="slider"— focus it and use Arrow keys (Shift+Arrowfor a 1-unit step) to nudge the head. - Spring transitions. Heads animate with
SPRINGS.snapfrom@craft-bits/core/motion.prefers-reduced-motion: reducecollapses the spring toduration: 0.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
vectors | readonly Vector2D[] | required | Vectors to render. Index drives identity. |
range | readonly [number, number] | [-5, 5] | Visible math-space domain on both axes. |
showGrid | boolean | true | Paint the integer-spaced grid. |
showAxes | boolean | true | Paint the x / y axes through the origin. |
interactive | boolean | false | Make each arrow head a drag + focus handle. |
onVectorsChange | (next: Vector2D[]) => void | — | Fires on drag / keyboard nudge with the updated array. |
size | number | 320 | SVG side length in pixels (the plane is square). |
transition | Transition | SPRINGS.snap | Spring for vector-head transitions. |
className | string | — | Merged onto the root <div> via cn(). |
The Vector2D shape:
| Field | Type | Default | Description |
|---|---|---|---|
x | number | required | Head x in math coordinates. |
y | number | required | Head y in math coordinates. |
label | string | — | Optional label rendered near the head. |
tone | "default" | "accent" | "success" | "warning" | "error" | "default" | Visual tone for stroke + arrow. |
tail | { x: number; y: number } | { x: 0, y: 0 } | Tail point. Defaults to the origin. |
Accessibility
- The SVG is
role="img"with a visually hidden summary listing every vector's coordinates and magnitude. - When
interactive, each arrow head exposes arole="slider"invisible 32px hit target meeting WCAG 2.5.8 (Target Size, Enhanced). - Keyboard: focus a handle, then
←/→/↑/↓nudge in 0.25-unit steps.Shift+Arrownudges by 1 unit. The head clamps torange. - Animation respects
prefers-reduced-motion: reduce— vector-head transitions collapse to an instant swap.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/math/VectorVisualizer.tsx). The source was a dot-product lesson with explore / predict / challenge modes, narration heuristics, and presets baked in. The library extract is the pure visualization primitive — N vectors, optional drag, no lesson scaffolding.