Yfiles nodestyle basic
Skill yWorks/yfiles-for-html-skills/skills/yfiles-nodestyle-basic
Comprehensive Claude Code plugin for yFiles for HTML development - includes skills for initialization, graph building, layouts, custom styling, and interactive features
npx -y skills add yWorks/yfiles-for-html-skills --skill yfiles-nodestyle-basicAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
This skill should be used when the user asks to "create a custom node style", "implement NodeStyleBase", "create a custom node visualization", "implement createVisual", "implement updateVisual", "render nodes with SVG", or mentions "custom rendering", "TaggedSvgVisual", or "visual caching".
SKILL.md
5.3 KB, as published. Nobody here has run it
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
TaggedSvgVisualin one call - Render at origin + translate: Render the shape at
(0,0)and useSvgVisual.setTranslate()for position — only the transform needs updating when a node moves
Implementation Steps
- Declare a
Cachetype with the values needed to detect changes inupdateVisual - Declare a
CustomNodeStyleVisual = TaggedSvgVisual<TElement, Cache>type alias - Extend
NodeStyleBase<CustomNodeStyleVisual> - In
createVisual(): render at(0,0), set translate, returnSvgVisual.from(element, cache) - In
updateVisual(): readoldVisual.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 integrationreferences/reference.md— NodeStyleBase/SvgVisual API, SVG patterns, performance tips, common pitfalls