Skip to content

Selection & Accessibility ​

With interaction.selectable turned on, connections become keyboard- and screen-reader-friendly: each one is a focusable button that can be selected, and Delete asks the app to remove it. The library never changes your data — it only reports what the user did.

ts
const linker = createVisualLinker(el, { interaction: { selectable: true } })

linker.on('connection:selectionchange', ({ selectedIds }) => {})
linker.on('connection:delete-request', ({ connections }) => {}) // you remove them — or don't
linker.setSelectedConnections(['a-b']) // controlled use; emits nothing

How it behaves ​

  • Every connection is focusable. The Tab order is the order of connections.
  • A click, or Enter / Space on a focused line, selects that line alone.
  • Ctrl, Cmd or Shift together with the click or key toggles the line within a multi-selection.
  • Escape, or a pointer press anywhere outside the lines, clears the selection.
  • A selectable line shows a pointer cursor, with or without interaction.hover.
  • A connection that disappears drops out of the selection.
  • Delete or Backspace emits connection:delete-request with the selected connections — or, when the focused line isn't selected, just that one. Nothing is removed.

Look and feel ​

A selected line gets the same width bump a hover gets plus a halo. Change it with the selected state, which takes the same fields as hover. It sits between the base style and hover: while a line is both selected and hovered, hover wins. The halo color is the theme's selectedHalo (--vl-selected-color); the focus ring on the focused line is focusRing (--vl-focus-color). Markers, ports and labels have a selected state too — see Visual States.

selected ​

{ color?; width?; dashed?; opacity? } · default: — (unset, the default selected look)

On a connection's style or in the lines group. See Connection Styling.

Accessibility ​

Every visible line carries role="img" and an aria-label. Without interaction.selectable, the invisible hit path is hidden from assistive technology. With it, the hit path is tabindex="0" with role="button" and aria-pressed, and the focus is drawn on the visible line.

ariaLabel ​

string · default: "Connection: {from block id} → {to block id}"

On a ConnectionDescriptor. The accessible name of the line.

Options, methods and events ​

interaction.selectable ​

boolean · default: false

In the interaction group of the configuration. Off by default, so existing diagrams don't suddenly gain tab stops.

setSelectedConnections(ids: readonly string[]): void ​

A method of the engine. Replaces the selection. Ids not among the current connections are ignored. It emits no event, so the app can drive the selection without feedback loops.

connection:selectionchange ​

{ selectedIds: string[] }

The set of selected connections changed because of user input.

connection:delete-request ​

{ connections: ConnectionDescriptor[] }

Delete or Backspace was pressed on a focused connection.

In Vue ​

<VisualLinker> takes the selection as the selected prop — an array of connection ids, usable with v-model:selected. Leave it unset to let the engine own the selection. @connection-selectionchange receives the same array, and @connection-delete-request the connections to delete.

vue
<VisualLinker
  v-model:selected="selected"
  :connections="connections"
  :config="{ interaction: { selectable: true } }"
  @connection-delete-request="(requested) => remove(requested)"
>
  …
</VisualLinker>

See VisualLinker Component.