# Canvas element types

_Every element a Canvas can store, including geometry, style, bindings, membership, live embeds, and engine-owned data._

Canonical: https://snoze.dev/help/canvas-elements/

Every Canvas element is a flat record with an ID, type, position (`x`, `y`),
size (`w`, `h`), angle, fractional z-order index, deletion and collaboration
metadata, and a type-specific `props` object. Group, frame, and mind-map
membership uses IDs rather than nested records, so elements can move and sync
independently.

New writes use named style tokens, while colour strings, numeric stroke widths,
and numeric font sizes remain accepted for older elements.

<!-- GENERATED:canvas-element-types:START -->

Canonical contract values:

- `rectangle`
- `ellipse`
- `diamond`
- `triangle`
- `text`
- `note`
- `line`
- `arrow`
- `freehand`
- `image`
- `frame`
- `group`
- `mindmap`
- `edgeless-text`
- `plait`

<!-- GENERATED:canvas-element-types:END -->

## Elements

### Rectangle `rectangle`

A rectangular box with optional corner radius and text. Its style includes
fill, stroke, stroke width, dash, opacity, clean or scribbled rendering,
sloppiness, fill style, edge style, and font, weight, style, size, colour, and
alignment. It may be locked or belong to a frame, group, or mind map.

### Ellipse `ellipse`

An oval using the same paint, hand-drawn look, text, and membership settings as
a Rectangle, except it has no corner-radius setting. Its default box is square,
but its width and height may differ.

### Diamond `diamond`

A decision-style diamond rendered with the Rectangle prop contract: fill,
stroke, dash, opacity, look, optional text, radius-compatible legacy data, and
membership. The type controls geometry; the stored props do not contain four
corner points.

### Triangle `triangle`

A triangular shape with the same shared box, text, look, and membership
settings as Rectangle. Rotation comes from the element record's `angle` rather
than a triangle-specific property.

### Text `text`

A lightweight editable text element. It stores text, a block style
(`paragraph`, heading 1–6, code, quote, bulleted, numbered, or to-do), colour,
font size and family, alignment, opacity, and membership. It omits font weight
and italic settings; use Edgeless text when those are needed.

### Note `note`

A card that can be a sticky note, page card, embed, or file card. Besides text
and typography it may store title, URL, file identity, linked workspace item,
link-preview metadata, embed view, and a snapshot of page blocks. A linked
database may use `databaseId` plus the card's own embedded view kind and
manifest; older static database previews still decode as a fallback.

### Line `line`

A connector without arrowheads. Its points are stored relative to the element
box; it also stores stroke, width, dash, opacity, and straight, curved, or
orthogonal routing. Optional start and end bindings name another element and a
normalised anchor, so the line reroutes when that shape moves.

### Arrow `arrow`

A Line with optional start and end arrowhead kinds and a text label. It has the
same point geometry, routing modes, bindings, paint, opacity, locking, and
container membership. A missing binding leaves that endpoint free-floating.

### Freehand `freehand`

A drawn stroke made from box-relative point samples. Points may carry pointer
pressure; the renderer turns them into an outline. Props contain stroke, width,
opacity, and membership, but no fill, dash, routing mode, or arrowhead.

### Image `image`

An asset image selected by canonical `fileId`, with a resolved `src`, alt text,
optional template or sticker asset kind, and object fit of cover, contain, or
fill. Natural pixel dimensions support aspect-aware resizing. The URL may be
absent until asset resolution completes.

### Frame `frame`

A titled spatial container. It stores name, fill, opacity, whether children are
clipped, and optional zero-based presentation order. Children persist the
frame's ID in their own props. Frames own members by spatial containment and
move or clip them; the current contract does not support nesting frames.

### Group `group`

A zero-cost grouping container with optional name and locked state. Members
point back by group ID, so selecting or transforming the group fans out to
them. Unlike a Frame, a Group has no visible fill, header, clipping, or
containment-based membership.

### Mind map `mindmap`

The root of a live mind map. It stores root node ID, member node IDs, style
preset one through four, layout `balance`, `left`, or `right`, and locked state.
Member nodes and connectors point back with `mindmapId`; the root does not
embed their full records.

### Edgeless text `edgeless-text`

A richer floating text block. It stores the same block-style vocabulary as
Text plus font weight and font style, colour, size, family, alignment, opacity,
locking, and container membership. It is editable as text but remains a Canvas
element, not a Page block.

### Plait `plait`

A native document node owned by the Plait whiteboard engine. Snoze stores a
required JSON-safe `data` payload with the engine node's top-level ID omitted;
the Canvas element ID remains canonical for events and sync. Snoze validates
the outer element geometry and identity, but the internal grammar belongs to
Plait and is intentionally not described by individual Snoze props.

## Behaviour by element role

Line and Arrow are connector types. Line, Arrow, and Freehand are point-based.
Frame, Group, and Mind map are container types, with the different ownership
rules described above. Text, Note, and Edgeless text expose direct text editing.
The shared style panel uses per-type rules, so it does not offer fill on
a connector or arrowheads on a rectangle.

Canvas changes are synchronised as insert, update, and delete operations.
Durable changes enter undo history; ephemeral drag updates are squashed before
they are stored and sent. This does not change the element vocabulary, but it
explains why a live drag is not hundreds of permanent history entries.