Free-form visual workspace.
<div class="canvas-demo">
<span class="canvas-demo__badge">Moodboard</span>
<div class="canvas-demo__surface canvas-demo__surface--zoom-100" style="background-size:24px 24px;">
<div class="canvas-demo__node" style="left:20px; top:18px; background:#A8E6C1;">A</div>
<div class="canvas-demo__node" style="left:120px; top:70px; background:#A8E6C1;">B</div>
<div class="canvas-demo__node" style="left:60px; top:130px; background:#A8E6C1;">C</div>
</div>
</div>
<style>
.canvas-demo { position: relative; font: 13px system-ui, sans-serif; color: #241430; }
.canvas-demo__badge { position: absolute; top: 8px; left: 8px; z-index: 2; background: #241430; color: #FAF7F2; padding: 3px 10px; border-radius: 999px; font-weight: 600; font-size: 12px; }
.canvas-demo__surface { position: relative; height: 200px; overflow: hidden; background-color: #FAF7F2; background-image: radial-gradient(#24143033 1px, transparent 1px); border: 1px solid #24143022; transform-origin: top left; }
.canvas-demo__surface--nogrid { background-image: none; }
.canvas-demo__surface--zoom-75 { transform: scale(.75); width: 133.3%; height: 266px; }
.canvas-demo__surface--zoom-125 { transform: scale(1.25); width: 80%; height: 160px; }
.canvas-demo__node { position: absolute; width: 44px; height: 44px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-weight: 700; color: #241430; box-shadow: 0 6px 14px rgba(36,20,48,.2); }
</style><div class="relative font-sans text-[13px] text-[#241430] canvas-tw">
<span class="absolute top-2 left-2 z-10 bg-[#241430] text-[#FAF7F2] px-2.5 py-1 rounded-full font-semibold text-xs">Moodboard</span>
<div class="relative h-[200px] overflow-hidden bg-[#FAF7F2] border border-[#24143022] origin-top-left canvas-tw__surface canvas-tw__surface--zoom-100" style="background-image:radial-gradient(#24143033 1px, transparent 1px); background-size:24px 24px;">
<div class="absolute w-11 h-11 rounded-[10px] flex items-center justify-center font-bold shadow-lg" style="left:20px;top:18px;background:#A8E6C1;">A</div>
<div class="absolute w-11 h-11 rounded-[10px] flex items-center justify-center font-bold shadow-lg" style="left:120px;top:70px;background:#A8E6C1;">B</div>
<div class="absolute w-11 h-11 rounded-[10px] flex items-center justify-center font-bold shadow-lg" style="left:60px;top:130px;background:#A8E6C1;">C</div>
</div>
</div>
<style>
.canvas-tw__surface--nogrid { background-image: none !important; }
.canvas-tw__surface--zoom-75 { transform: scale(.75); width: 133.3%; height: 266px; }
.canvas-tw__surface--zoom-125 { transform: scale(1.25); width: 80%; height: 160px; }
</style>export function Canvas({
label = "Moodboard",
spacing = 24,
accent = "#A8E6C1",
showGrid = true,
zoom = "100",
}) {
const scale = Number(zoom) / 100;
return (
<div style={{ position: "relative", fontFamily: "system-ui, sans-serif", fontSize: 13, color: "#241430" }}>
<span style={{ position: "absolute", top: 8, left: 8, zIndex: 2, background: "#241430", color: "#FAF7F2", padding: "3px 10px", borderRadius: 999, fontWeight: 600, fontSize: 12 }}>{label}</span>
<div style={{
position: "relative", height: 200, overflow: "hidden", background: "#FAF7F2",
backgroundImage: showGrid ? "radial-gradient(#24143033 1px, transparent 1px)" : "none",
backgroundSize: `${spacing}px ${spacing}px`, border: "1px solid #24143022",
transform: `scale(${scale})`, transformOrigin: "top left", width: `${100 / scale}%`,
}}>
{[{ id: "A", x: 20, y: 18 }, { id: "B", x: 120, y: 70 }, { id: "C", x: 60, y: 130 }].map((n) => (
<div key={n.id} style={{ position: "absolute", left: n.x, top: n.y, width: 44, height: 44, borderRadius: 10, background: accent, display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 700, boxShadow: "0 6px 14px rgba(36,20,48,.2)" }}>{n.id}</div>
))}
</div>
</div>
);
}