Core Concepts
Design Elements
Everything on the canvas is a design element. Learn about element types, their properties, and how to create and manipulate them.
Base Element Interface
Common properties shared by all elements
interface BaseElement {
// Identity
id: string // Unique identifier (auto-generated)
type: ElementType // Element type discriminator
name?: string // Optional display name
// Position
x: number // X coordinate
y: number // Y coordinate
// Transform
rotation?: number // Rotation in degrees (default: 0)
opacity?: number // Opacity 0-1 (default: 1)
// Visual
fill?: string // Fill color (CSS color or gradient)
stroke?: string // Stroke color
strokeWidth?: number // Stroke width in pixels
// State
locked?: boolean // Prevent selection/editing
visible?: boolean // Show/hide element
// Metadata
metadata?: Record<string, unknown> // Custom data
created_at?: string // ISO timestamp
updated_at?: string // ISO timestamp
}
type ElementType =
| "rectangle"
| "ellipse"
| "line"
| "text"
| "image"
| "path"
| "group"Element Types
rectangle
Basic rectangle shape with rounded corners support
xywidthheightfillstrokestrokeWidthcornerRadiusrotationopacityellipse
Circles and ellipses defined by radii
xyrxryfillstrokestrokeWidthrotationopacityline
Straight line between two points
x1y1x2y2strokestrokeWidthstrokeDasharrayopacitytext
Text content with font styling
xycontentfontSizefontFamilyfontWeightfilltextAlignrotationopacityimage
Raster or vector images from URL or upload
xywidthheightsrcpreserveAspectRatiorotationopacitypath
Custom SVG paths for complex shapes
dfillstrokestrokeWidthfillRulerotationopacitygroup
Container for grouping multiple elements
xychildrenrotationopacityType Definitions
Complete TypeScript interfaces for each element type
interface RectangleElement extends BaseElement {
type: "rectangle"
width: number
height: number
cornerRadius?: number | {
topLeft: number
topRight: number
bottomRight: number
bottomLeft: number
}
}
// Example
const rect: RectangleElement = {
id: "rect_001",
type: "rectangle",
x: 100,
y: 100,
width: 200,
height: 150,
fill: "#3b82f6",
stroke: "#1d4ed8",
strokeWidth: 2,
cornerRadius: 8,
rotation: 0,
opacity: 1
}Element Manipulation
Create, update, and delete elements programmatically
// Creating elements
// Via canvas API
const rect = canvas.addElement({
type: "rectangle",
x: 100,
y: 100,
width: 200,
height: 150,
fill: "#3b82f6"
})
// Via store action
import { useDesignStore } from "@/lib/design/store"
const addElement = useDesignStore(state => state.addElement)
addElement({
type: "text",
x: 200,
y: 200,
content: "New Text",
fontSize: 24,
fill: "#000000"
})
// Via API
const response = await fetch('/api/v1/designs/design_123/elements', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: "ellipse",
x: 300,
y: 300,
rx: 50,
ry: 50,
fill: "#10b981"
})
})Element Grouping
Organize elements into hierarchical groups
// Grouping elements
// Create group from selection
const group = canvas.groupSelected()
// Returns: { id: "group_001", type: "group", children: [...] }
// Create group programmatically
const group = canvas.createGroup([elementId1, elementId2, elementId3])
// Ungroup
canvas.ungroup(groupId)
// Returns children to top level
// Group interface
interface GroupElement extends BaseElement {
type: "group"
children: DesignElement[]
}
// Nested groups are supported
const nestedGroup = canvas.createGroup([groupId1, elementId4])
// Access children
const children = canvas.getGroupChildren(groupId)
// Move element into group
canvas.moveToGroup(elementId, groupId)
// Move element out of group
canvas.moveToParent(elementId) // Moves to canvas rootZ-Order (Layering)
Control element stacking order
// Z-order operations
// Bring to front (topmost)
canvas.bringToFront(elementId)
// Send to back (bottommost)
canvas.sendToBack(elementId)
// Move forward one level
canvas.bringForward(elementId)
// Move backward one level
canvas.sendBackward(elementId)
// Set specific z-index
canvas.setZIndex(elementId, 5)
// Get z-index
const zIndex = canvas.getZIndex(elementId)
// Swap z-order of two elements
canvas.swapZOrder(elementId1, elementId2)
// Reorder multiple elements
canvas.reorderElements([
{ id: "el_1", zIndex: 0 },
{ id: "el_2", zIndex: 1 },
{ id: "el_3", zIndex: 2 }
])Element Events
Listen for element-specific events
// Element event handling
// Listen for element creation
canvas.on('elementCreated', (element) => {
console.log('New element:', element.id, element.type)
})
// Listen for element updates
canvas.on('elementUpdated', (element, changes) => {
console.log('Updated:', element.id, changes)
})
// Listen for element deletion
canvas.on('elementDeleted', (elementId) => {
console.log('Deleted:', elementId)
})
// Listen for selection changes
canvas.on('selectionChanged', (selectedElements) => {
console.log('Selected:', selectedElements.length)
})
// Listen for drag events
canvas.on('elementDragStart', (element, position) => {
console.log('Drag start:', element.id)
})
canvas.on('elementDragEnd', (element, position) => {
console.log('Drag end:', element.id, position)
})
// Remove listener
const unsubscribe = canvas.on('elementCreated', handler)
unsubscribe() // Clean upRelated Documentation
- Learn about the Canvas Engine
- Explore Export System
- See Drag and Drop interactions