Visual States
A connection looks different while the pointer is over it, while it is selected, or while it has keyboard focus. Every visual entity — lines, markers, ports and labels — describes those looks the same way: its own fields, plus one bucket per state with the fields that change.
lines: {
color: '#2e8b57',
width: 2,
hover: { width: 4, dashed: true },
selected: { color: '#1f6feb' },
}The four states
hover— the pointer is over the connection's own line. Needsinteraction.hover.highlight— the pointer is over one of the connection's blocks, which lights up every connection that ends there. Needsinteraction.highlight. Until ahighlightbucket is set, it looks the same ashover; set it to make a block's lines react more quietly than a line under the pointer.selected— the connection is selected (see Selection & Accessibility).focus— the connection's line has keyboard focus.
States combine. A connection that is selected and hovered gets the selected fields, then the hover fields on top. The order, from weakest to strongest:
- the entity's own fields,
selected,highlight,hover,focus.
A field that no active state sets keeps the value from the layer below.
Turning hover and highlight on
hover and highlight are off by default: a diagram that is only looked at does not react to the pointer, and its lines show no pointer cursor. Turn them on in the interaction group of the configuration:
interaction: { hover: true, highlight: true }interaction.hover—boolean· default:false. The pointer over a line puts it into thehoverstate and shows a pointer cursor over it.interaction.highlight—boolean· default:false. The pointer over a block puts the connections that end there into thehighlightstate.
Each can be set for a single entity, and the local value wins over the global one: hoverable on a connection and highlightable on a block. hoverable: false keeps one line still while everything else reacts; highlightable: true lets one block light up its lines on a diagram that is otherwise still.
A hover or highlight bucket does nothing while its mode is off. The selected and focus states, selection and keyboard operation do not depend on either flag, and a selectable line shows the pointer cursor anyway. The events connection:mouseenter, connection:mouseleave, block:mouseenter and block:mouseleave fire either way. Both flags can be changed at runtime with setConfig.
What a state can change
A state bucket takes the same fields as the entity itself:
- Lines —
color,width,dashed,opacity. Without a state width, a selected or highlighted line still gets a small width bump over its explicit width, so it stands out. - Markers —
shape,size,color,strokeColor,strokeWidth,opacity,svg,arrow. A marker can turn from a dot into a diamond on hover, or swap a whole customsvg. - Ports —
radius,fill,stroke,strokeWidth,opacity. - Labels —
background,border,color,fontSize,paddingX,paddingY,opacity.
Markers, ports and labels follow the state of their connection. A port dot shared by several connections takes the strongest state among them. Blocks have no states: they are your own markup, and the engine only adds the classes vl-draggable and vl-dragging, so restyle them with CSS.
A marker follows its line
A marker that sets no color is painted in the color the line has in the current state. When a line turns red on hover, its arrow turns red with it, with no marker setting at all. A color set on the marker itself is kept in every state, unless that state's bucket sets another.
markers: {
end: {
shape: 'circle',
size: 6,
hover: { shape: 'diamond', size: 10, strokeColor: '#ffffff', strokeWidth: 1 },
selected: { shape: 'arrow', size: 8 },
},
}A marker's size is a multiple of the line's stroke width, so it grows by itself when the line gets thicker; a size in a state bucket overrides that.
Setting states in several places
The configuration group and a connection's own style both have buckets. They merge state by state and field by field: a connection's hover.width replaces the group's hover.width, and the group's hover.color still applies.
createVisualLinker(el, { lines: { hover: { color: '#6366f1', width: 4 } } })
linker.setConnections([
{ id: 'a-b', from, to, style: { hover: { width: 6 } } }, // hover: width 6, color '#6366f1'
])A state bucket ranks above the base fields at every level. When the group sets hover.color and a connection sets only its own base color, that connection shows the group's hover color on hover. To keep its own color, the connection sets hover.color as well.
Keyboard focus
The focus state applies to connections that can take focus, which needs interaction.selectable. A focused line gets a halo in the theme's focusRing color on top of whatever focus sets.
Opacity
opacity is a field of its own, so it can change in a state: fade connections at rest and bring one to full strength on hover.
lines: { opacity: 0.55, hover: { opacity: 1 } }A marker without its own opacity fades together with its line. An animated line is dimmed further to let the moving pattern show, so its effective opacity is the two multiplied.