GuidesCSS Layout & Selection

CSS Layout & Selection System

Canvus manages node hierarchies and layouts by combining an in-memory tree model with CSS display introspection and canvas drop target estimation.


Hierarchical Tree Model (NodeTree)

The workspace doesn’t query the DOM repeatedly to determine parent-child relationships. Instead, NodeTree keeps an in-memory representation of the document structure.

  • Node Hierarchy: Nodes contain parentId and childIds references. Root-level elements have parentId = null
  • Topological Depth: The tree calculates a depth index (0 for root, 1 for direct children, etc.) for each node. This determines visual rendering order and breadcrumb paths
  • Reparenting Safety: When moving nodes, the tree runs cycle-detection algorithms. It walks ancestor branches of the target parent to ensure a node is never reparented to one of its own descendants

Mutation APIs

Always use the Workspace APIs to mutate structures:

ws.addNode(node, parentId, index)   // Mount and register in NodeTree
ws.removeNode(nodeId)                // Detach wrappers and clean tree
ws.reparentNode(nodeId, parentId)    // Swap DOM parents and update tree
ws.reorderChild(nodeId, index)       // Move sibling indexes and update children
⚠️

Never mutate parentId or childIds directly. Always use the Workspace mutation APIs to maintain safety invariants and prevent circular hierarchies.


Layout Introspection

The layout introspection engine (layout.ts) reads computed CSS variables from elements to determine visual overlay behavior.

Display Detection

When a container is measured, the engine calls getComputedStyle(element) to detect:

  • display mode: flex, grid, block, or inline
  • Flex axes: Reads flex-direction (row vs. column) and flex-wrap values
  • Grid configurations: Evaluates columns/rows and parses gap definitions

Spacing Adjusters (Margins & Paddings)

When a single node is selected, Canvus renders hoverable margin/padding drag boxes on the canvas overlay:

  1. Reading Bounds: Reads computed margins (margin-top, margin-left, etc.) and paddings
  2. Visual Overlays: Paints drag bars representing padding (inside content boundaries) or margins (outside content boundaries) with values displayed in tooltips
  3. Style Surgery: Dragging an adjuster translates pointer coordinates into inline style changes. The browser reflows elements, the ResizeObserver detects changed rectangles, and the canvas overlay updates

Drop Zone & Drag-and-Drop Insertion

When a node is dragged, Canvus calculates potential placement zones in real-time.

Drop Target Estimation

  1. Container Hit Testing: Identifies which container node bounds cover the current pointer position
  2. Layout-Aware Slot Calculations:
    • Flex Containers: Projects the pointer onto the active flex axis (row or column). Slices boundaries between existing children to identify index slots
    • Grid Containers: Projects coordinates onto grid tracks (columns/rows) to resolve slot cells
    • Block Flow: Measures vertical centerlines of siblings to find insertion slots
  3. Insertion Indicators: Draws horizontal or vertical coordinate lines on the canvas overlay

Figma-Style Selection Semantics

Canvus uses drill-down selection rules for navigating deeply nested hierarchies:

GestureBehavior
Single ClickSelects the topmost element in the active scope. Clicking outside clears selection
Double ClickDrills down into the clicked node’s subtree scope
Cmd/Ctrl + ClickDeep selection — bypasses drill-down and directly selects the leaf node
Shift + ClickMulti-selection — adds or removes nodes from the selection set