Skip to content

pivotick v3.0.0


pivotick / RendererOptions / NodeStyle

Interface: NodeStyle ​

Defined in: interfaces/RendererOptions.ts:468

Properties ​

badges? ​

optional badges: (node) => NodeBadge[] | NodeBadge[]

Defined in: interfaces/RendererOptions.ts:585

Small indicators pinned to the node's rim, independent of every other channel — see NodeBadge.

Resolved like any other channel: the narrowest declaration wins outright rather than merging, so a node's own badges replaces whatever nodeStyleMap or defaultNodeStyle gave it. An empty array is the way to say "this one wears none"; undefined renders no badge group at all.

Four fit on a plain node, two on one with children (the expand affordance reserves the East corners). Anything beyond that collapses into a +n badge naming the rest.


color ​

color: string | (node) => string

Defined in: interfaces/RendererOptions.ts:478

The main color of the node

Default ​

ts
'var(--pvt-node-color, #007acc)'

focusTier? ​

optional focusTier: Clearable<Omit<Partial<NodeStyle>, "tiers" | "focusTier" | "focusTierYieldsAt" | "layoutSize" | "styleCb">>

Defined in: interfaces/RendererOptions.ts:615

The drawing used while this node is hovered, or selected on its own — whatever the zoom. This is where a node says everything about itself.

It merges over the resolved base style rather than over the active tier, so a chip tier's shape or html cannot leak into it, and it holds a constant size on screen however far the graph is zoomed out. It never changes the node's geometry: edges keep landing on the tier underneath and nothing moves.

When it fires is GraphRendererOptions.focusTierTrigger's to say.


focusTierYieldsAt? ​

optional focusTierYieldsAt: number

Defined in: interfaces/RendererOptions.ts:630

The index into tiers from which focusTier stops firing. While the node is drawn at that tier or a richer one, hover and a lone selection leave it as it is, for a focus drawing that the zoom tier already shows. Unset, the focus drawing fires at every tier. Ignored on a node with no tiers.

Example ​

ts
// Hovering the dot shows the chip; once the chip tier is drawn, hovering adds nothing.
tiers: [{ width: 140, height: 44, style: { shape: 'none', html: chipFor } }],
focusTier: { shape: 'none', html: chipFor },
focusTierYieldsAt: 0,

fontFamily ​

fontFamily: string

Defined in: interfaces/RendererOptions.ts:486

Default ​

ts
'var(--pvt-font-family)'

html()? ​

optional html: (node) => string | void | HTMLElement

Defined in: interfaces/RendererOptions.ts:572

The html to be used inside the node as an SVGForeignObject element.

Resolved like every other channel, so a card can be declared at any level — nodeStyleMap[type].html gives one kind of node a card while the rest keep their shapes, and a single node's own style overrides that. Returning nothing draws no card, so one callback can card some nodes and leave the others alone.

Pair it with shape: 'none' for a card that is the node. Otherwise the shape is still drawn behind it, and size is the smallest the node can be.

The card is measured and the node grows to it, so it is never clipped and edges land on its border. You do not have to make the returned element self-sizing — it is measured inside a shrink-to-fit box, so width: 100% resolves against its own content rather than against the placeholder.

Trusted HTML only. Whatever this returns is inserted as-is, so build it with textContent (or escape it) rather than interpolating node data into a markup string.

Parameters ​

node ​

Node

Returns ​

string | void | HTMLElement


iconClass? ​

optional iconClass: string

Defined in: interfaces/RendererOptions.ts:530


iconUnicode? ​

optional iconUnicode: string

Defined in: interfaces/RendererOptions.ts:531


imageFit? ​

optional imageFit: (node) => ImageFit | ImageFit

Defined in: interfaces/RendererOptions.ts:548

How an imagePath picture sits on the node's shape. Resolvable per node so different nodes can mix modes (e.g. screenshots 'cover', other attachments 'icon').

Default ​

ts
'icon'

imagePath? ​

optional imagePath: string

Defined in: interfaces/RendererOptions.ts:542

URL of a picture to draw on the node. Restricted to the http:, https:, data: and blob: schemes; anything else is ignored. Rendering it fetches the URL.


layoutSize? ​

optional layoutSize: number

Defined in: interfaces/RendererOptions.ts:641

The half-width of the box this node reserves for itself in the layout, in graph units. This is the only size the simulation ever sees: set it and the drawing no longer drives the collision radius, so a node can change how it is drawn without moving anything.

Leave it unset and the drawing owns the spacing, as it always has — a shape spaces by its size, an HTML card by what it measures.

Default ​

half the widest declared tier width, or unset when there are no tiers


shape ​

shape: (node) => NodeShape | NodeShape

Defined in: interfaces/RendererOptions.ts:473

The shape of the node, either a standard shape or a custom SVG path

Default ​

ts
circle

size ​

size: number | (node) => number

Defined in: interfaces/RendererOptions.ts:480

Default ​

ts
10

strokeColor ​

strokeColor: string | (node) => string

Defined in: interfaces/RendererOptions.ts:482

Default ​

ts
'var(--pvt-node-stroke, #fff)'

strokeWidth ​

strokeWidth: string | number

Defined in: interfaces/RendererOptions.ts:484

Default ​

ts
'var(--pvt-node-stroke-width, 2)'

styleCb()? ​

optional styleCb: (node) => Partial<NodeStyle>

Defined in: interfaces/RendererOptions.ts:653

Callback to dynamically override style properties based on the node.

Where it sits depends on which style block declares it. On a node's own style it wins outright, and nodeStyleMap is skipped entirely. On render.defaultNodeStyle it is the computed form of the default slot: it fills only what neither the node nor nodeStyleMap set (and what a per-node styleCb left out), and its result still loses to both.

Runs once per node per render, so keep it cheap.

Parameters ​

node ​

Node

Returns ​

Partial<NodeStyle>


svgIcon? ​

optional svgIcon: string

Defined in: interfaces/RendererOptions.ts:537

Inline SVG markup drawn inside the node. Sanitized before it reaches the DOM (scripting and event handlers are stripped), but a remote <image href> inside it is still fetched when the node renders — see the security guide.


text? ​

optional text: string | (node) => string

Defined in: interfaces/RendererOptions.ts:552

The text to be used inside the node as an SVGText element


textAnchorPosition ​

textAnchorPosition: "end" | "start" | "middle"

Defined in: interfaces/RendererOptions.ts:490

Default ​

ts
'middle'

textColor ​

textColor: string | (node) => string

Defined in: interfaces/RendererOptions.ts:488

Default ​

ts
'var(--pvt-node-text-color, #fff)'

textFontSize? ​

optional textFontSize: number | (node) => number

Defined in: interfaces/RendererOptions.ts:529

Font size of the node's label, in graph units (CSS pixels at zoom 1). The label's offset, its built-in character budget and the zoom gate all follow it.

Default ​

ts
undefined — derived from the node's size: max(12, size × 0.45)

textHorizontalShift ​

textHorizontalShift: number | (node) => number

Defined in: interfaces/RendererOptions.ts:497

The horizontal shift applied to the node's label position. A value of 0 means it is centered to the node, a value of 1 is east of the node, -1 is west of the node. Other values are also accepted, e.g., 0.5 would be halfway between the center and the east of the node.

Default ​

ts
0

textMaxWidth? ​

optional textMaxWidth: number | (node) => number

Defined in: interfaces/RendererOptions.ts:523

Widest a node label may be drawn, in graph units (CSS pixels at zoom 1). A longer label is shortened with a middle ellipsis to fit. Replaces the built-in budget, which is sized to the node. Ignored when textTruncate is false.

Default ​

ts
undefined — the built-in budget

textRotateDegree ​

textRotateDegree: number | (node) => number

Defined in: interfaces/RendererOptions.ts:510

Rotation degree applied to the node's label. Positive values rotate clockwise, negative values rotate counter-clockwise.

Default ​

ts
0

textTruncate ​

textTruncate: boolean | (node) => boolean

Defined in: interfaces/RendererOptions.ts:516

Shorten an over-wide label with a middle ellipsis (head…tail); false draws it in full, on a themed pill where it spills past the node.

Default ​

ts
true

textVerticalShift ​

textVerticalShift: number | (node) => number

Defined in: interfaces/RendererOptions.ts:504

The vertical shift applied to the node's label position. A value of 0 means it is centered to the node, a value of 1 is north of the node, -1 is south of the node. Other values are also accepted, e.g., 0.5 would be halfway between the center and the north of the node.

Default ​

ts
0

tiers? ​

optional tiers: NodeTier[]

Defined in: interfaces/RendererOptions.ts:603

Alternative drawings of this node, chosen by how large it currently renders — a glyph on an overview, a labelled chip once there is room for one, a card once there is room for that. Ordered smallest first; the richest one that fits wins, and the base style is the floor when none do.

The node's footprint never changes with the drawing (see layoutSize), so swapping tiers moves nothing.

Example ​

ts
tiers: [
  { width: 32, height: 32, style: { shape: 'circle', size: 16 } },
  { width: 140, height: 44, style: { shape: 'none', html: chipFor } },
]