Get the FREE Ultimate OpenClaw Setup Guide →

Yfiles Nodestyle Basic

Scanned
npx machina-cli add skill yWorks/yfiles-for-html-claude-plugin/yfiles-nodestyle-basic --openclaw
Files (1)
SKILL.md
5.3 KB

Basic Custom Node Styles

Create custom node visualizations by extending NodeStyleBase and implementing SVG rendering with typed visual caching.

Before Creating

Always query the yFiles MCP for current API:

yfiles:yfiles_get_symbol_details(name="NodeStyleBase")
yfiles:yfiles_get_symbol_details(name="TaggedSvgVisual")
yfiles:yfiles_list_members(name="NodeStyleBase")
yfiles:yfiles_search_documentation(query="custom node style")

Quick Start (Minimal)

The simplest possible style — no caching, no updateVisual. Suitable for prototyping but not recommended for larger graphs.

import { NodeStyleBase, SvgVisual, type IRenderContext, type INode } from '@yfiles/yfiles'

export class CustomNodeStyle extends NodeStyleBase {
  protected createVisual(context: IRenderContext, node: INode): SvgVisual {
    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
    const { x, y, width, height } = node.layout
    rect.setAttribute('x', String(x))
    rect.setAttribute('y', String(y))
    rect.setAttribute('width', String(width))
    rect.setAttribute('height', String(height))
    rect.setAttribute('fill', '#0b7189')
    return new SvgVisual(rect)
  }
}

Recommended Pattern (Typed Cache + updateVisual)

For production implementations, declare a Cache type and a named visual type using TaggedSvgVisual, then pass it as the type argument to NodeStyleBase. This enables typed access to visual.tag in updateVisual and avoids recreating DOM elements on every render frame.

import {
  NodeStyleBase,
  SvgVisual,
  TaggedSvgVisual,
  type IRenderContext,
  type INode
} from '@yfiles/yfiles'

// 1. Declare the cache shape
type Cache = { width: number; height: number }

// 2. Declare the visual type — ties the SVG element type to the cache type
type CustomNodeStyleVisual = TaggedSvgVisual<SVGPathElement, Cache>

// 3. Pass the visual type as the type argument to NodeStyleBase
export class CustomNodeStyle extends NodeStyleBase<CustomNodeStyleVisual> {
  protected createVisual(
    context: IRenderContext,
    node: INode
  ): CustomNodeStyleVisual {
    const { x, y, width, height } = node.layout
    const pathElement = document.createElementNS(
      'http://www.w3.org/2000/svg',
      'path'
    )
    // Render at (0,0) and position via transform — required for efficient updates
    pathElement.setAttribute('d', createPathData(0, 0, width, height))
    SvgVisual.setTranslate(pathElement, x, y)
    pathElement.setAttribute('fill', '#0b7189')
    pathElement.setAttribute('stroke', '#042d37')
    // SvgVisual.from() creates a TaggedSvgVisual with the cache stored in .tag
    return SvgVisual.from(pathElement, { width, height })
  }

  protected updateVisual(
    context: IRenderContext,
    oldVisual: CustomNodeStyleVisual,
    node: INode
  ): CustomNodeStyleVisual {
    const { x, y, width, height } = node.layout
    const pathElement = oldVisual.svgElement
    const cache = oldVisual.tag  // fully typed as Cache

    // Only rebuild the path when size actually changed
    if (width !== cache.width || height !== cache.height) {
      pathElement.setAttribute('d', createPathData(0, 0, width, height))
      oldVisual.tag = { width, height }
    }

    // Always update position via transform
    SvgVisual.setTranslate(pathElement, x, y)
    return oldVisual
  }
}

Core Concepts

  • createVisual(): Creates the SVG visual (required)
  • updateVisual(): Reuses the existing DOM element, updating only what changed (highly recommended for larger graphs)
  • TaggedSvgVisual<TElement, TCache>: Typed wrapper that ties an SVG element type to a cache type via .tag
  • SvgVisual.from(element, cache): Convenience factory that creates a TaggedSvgVisual in one call
  • Render at origin + translate: Render the shape at (0,0) and use SvgVisual.setTranslate() for position — only the transform needs updating when a node moves

Implementation Steps

  1. Declare a Cache type with the values needed to detect changes in updateVisual
  2. Declare a CustomNodeStyleVisual = TaggedSvgVisual<TElement, Cache> type alias
  3. Extend NodeStyleBase<CustomNodeStyleVisual>
  4. In createVisual(): render at (0,0), set translate, return SvgVisual.from(element, cache)
  5. In updateVisual(): read oldVisual.tag (typed), update only changed attributes, always update translate

Related Skills

To extend this foundation:

  • /yfiles-nodestyle-configure — Make styles configurable and data-driven
  • /yfiles-nodestyle-interaction — Add hit testing and edge cropping
  • /yfiles-nodestyle-advanced — Viewport culling and group nodes

Additional Resources

  • references/examples.md — Complete examples: rectangle, custom path, group container, framework integration
  • references/reference.md — NodeStyleBase/SvgVisual API, SVG patterns, performance tips, common pitfalls

Source

git clone https://github.com/yWorks/yfiles-for-html-claude-plugin/blob/main/skills/yfiles-nodestyle-basic/SKILL.mdView on GitHub

Overview

Yfiles Nodestyle Basic shows how to build custom node visuals by extending NodeStyleBase and rendering with SVG. It covers both a simple, no-cache approach for prototyping and a recommended typed cache pattern using TaggedSvgVisual for production performance. The skill explains createVisual and updateVisual responsibilities and how to leverage visual caching.

How This Skill Works

Developers override createVisual in a subclass of NodeStyleBase to render an SVG element for a node. For production, declare a Cache shape and a CustomNodeStyleVisual type using TaggedSvgVisual, then implement updateVisual to reuse DOM when only layout data changes, updating transforms and attributes as needed.

When to Use It

  • When you need a fully custom node rendering (SVG) beyond default styles
  • When implementing a NodeStyleBase-based style for createVisual and updateVisual
  • When you want a minimal prototype with no caching
  • When you need typed access to the cached visual via .tag
  • When you want to optimize rendering by reusing DOM elements and transforms

Quick Start

  1. Step 1: Import NodeStyleBase and SvgVisual, create a class CustomNodeStyle extends NodeStyleBase, implement createVisual to render an SVG element
  2. Step 2: For production, declare a Cache type and a CustomNodeStyleVisual using TaggedSvgVisual, and implement updateVisual to reuse the DOM
  3. Step 3: Apply the style to your graph and observe how visuals are positioned via transforms and updated efficiently

Best Practices

  • Start with a minimal createVisual to prototype, then add caching for production
  • Use a Typed Cache and TaggedSvgVisual to store dimensions and state for updateVisual
  • Render content at (0,0) and position via SvgVisual.setTranslate for efficient updates
  • Only rebuild path or geometry in updateVisual when size or layout actually changes
  • Avoid recreating DOM elements on every render frame to maximize performance

Example Use Cases

  • A simple CustomNodeStyle that draws a filled rectangle for each node
  • A path-based node using a cached SVG element and transform positioning
  • Typed cache pattern with CustomNodeStyleVisual to access .tag in updateVisual
  • updateVisual that updates transforms and attributes without DOM recreation
  • Prototype example with no caching to rapidly test visuals

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers