Visual language
graphraum ships with an opinionated visual baseline so a first render is legible and recognizably graphraum before an application adds domain semantics.
Canonical palette
Section titled “Canonical palette”#040F0Fcanvas#226F54nodes and edges#FCFFFCselectionThe exported graphraumTheme is the source of truth for these defaults:
import { graphraumTheme } from "@domudev/graphraum";
console.log(graphraumTheme);// {// background: "#040f0f",// edge: "#226f54",// node: "#226f54",// selectedNode: "#fcfffc",// }Node states
Section titled “Node states”Inherits theme.node unless the node supplies color.
node.color carries product meaning and wins over the theme.
theme.selectedNode temporarily wins without changing graph data.
Viewport culling removes off-screen 2D nodes from the active instance range.
Selection is a color change inside the existing instanced node mesh. It deliberately does not add a halo mesh or another rendering pass, so the two-draw-call baseline remains true.
Override without forking
Section titled “Override without forking”Override only the tokens your product owns. The remaining values continue to follow the canonical theme.
const graph = new Graphraum(container, { theme: { node: "#6d5bd0", selectedNode: "#fcfffc", },});Per-node colors remain available for semantic categories:
graph.setData({ nodes: [ { id: "person:ada", position: { x: -20, y: 0 } }, { id: "place:london", position: { x: 20, y: 0 }, color: "#73c7a5" }, ], edges: [{ id: "born-in", source: "person:ada", target: "place:london" }],});Keep meaning outside color alone
Section titled “Keep meaning outside color alone”The WebGL surface is not the accessibility tree. Applications should mirror focus and selection into an accessible node list, expose labels in HTML, and pair semantic colors with text, shape, or filtering controls. graphraum owns the fast visual primitive; the host owns understandable interaction.
Built-in node shapes
Section titled “Built-in node shapes”Arbitrary HTML per node is not the dense rendering path: it would trade away batching, viewport materialization, and the 100k-node target. The defineVisuals() translation layer maps typed domain attributes to node and edge visuals once at ingestion, then compiles them into GPU buffers. Titles, properties, and host-owned action descriptors remain available by entity ID.
circle, square, diamond, hexagon, triangle, pill, and rounded are rendered as signed-distance fields on one instanced billboard geometry. Mixing them does not add meshes, materials, or draw calls, and the same shapes face the camera in 2D and 3D. Picking applies the same shape boundary—including any stroke—in world space for 2D and projected screen space for 3D.
Every shape accepts an independent width and height (square by default) plus an optional strokeWidth and strokeColor for an SDF ring around the outer edge. strokeColor falls back to theme.nodeStroke, the third canonical Porcelain swatch, so a stroked node stays on-palette without an explicit color.
Edge width, dash styles, direction markers, and path kinds (straight, quadratic, cubic) render as one instanced GPU edge batch, packing segment and marker instances into the same edge draw call rather than one object per edge. Curves compile to polylines at pack time. The overview LOD tier drops markers and forces solid, theme-width, straight segments first to keep frame time flat at scale; detail renders the full per-edge style and path. A future HTML adapter may project a strictly bounded focused or selected subset for rich product controls while the core remains framework-neutral.
Follow the design and benchmark acceptance criteria in the node and edge visual translation issue.