Skip to content
D
Documentation

A11y — functions

reference
3 min readUpdated

Functions

Import these from @grafloria/renderer.

Functions

analyseTopology

ts
function analyseTopology(diagram: DiagramLike): Topology

boundsOfPoints

The world bounds of a routed link — its polyline, grown a little.

ts
function boundsOfPoints(
  points: { x: number; y: number }[],
  pad = 8
): Rectangle | null

buildAdjacency

ts
function buildAdjacency(diagram: DiagramLike): Adjacency

buildOutline

ts
function buildOutline(diagram: DiagramLike): DiagramOutline

childrenByParent

Group/parent containment: parentId → child nodes.

ts
function childrenByParent(diagram: DiagramLike): Map<string, NodeModel[]>

degreeOf

Incoming / outgoing degree of a node. Self-loops count on both sides.

ts
function degreeOf(
  nodeId: string,
  diagram: DiagramLike
): { incoming: number; outgoing: number }

diagramAccessibleName

The canvas's own accessible name: "Diagram, 12 nodes, 14 edges". Read when focus first enters the canvas, so the user knows the size of what they have landed in before they start walking it.

ts
function diagramAccessibleName(diagram: DiagramLike, title?: string): string

diagramOf

Resolve the diagram off an engine, tolerating a bare DiagramModel.

ts
function diagramOf(engine: DiagramEngine | DiagramLike | undefined): DiagramLike | undefined

diagramRoleDescription

The aria-roledescription for the whole canvas.

ts
function diagramRoleDescription(diagramType?: string): string

edgeAccessibleName

An edge's ACCESSIBLE NAME.

"Edge from Start to Is order valid?, labelled yes, selected"

ts
function edgeAccessibleName(link: LinkModel, diagram: DiagramLike): string

edgeRoleDescription

The aria-roledescription for an edge. Respects the link's own semantics.

ts
function edgeRoleDescription(link: LinkModel): string

ensureMotionPreferenceStyles

Inject the motion-preference stylesheet once per document.

Idempotent and SSR-safe: no document → no-op, and a second call finds the existing element by id and returns it.

ts
function ensureMotionPreferenceStyles(doc?: Document): HTMLStyleElement | undefined

findComponents

Connected components, treating edges as undirected.

ts
function findComponents(diagram: DiagramLike, adjacency: Adjacency): string[][]

findCycles

Every cycle reachable in the directed graph, found by DFS with a colour mark. Reported once each, normalised to start at its smallest node id so the same cycle is never announced twice under two rotations.

ts
function findCycles(diagram: DiagramLike, adjacency: Adjacency): string[][]

humaniseType

Humanise an unknown type: my_customNode → "My custom node".

ts
function humaniseType(type: string | undefined): string

incidentEdges

The edges incident on a node, ordered for keyboard traversal: outgoing first (the direction a reader follows a flow), then incoming, each in the reading order of the node at the far end — so pressing the same key twice always walks the same way.

ts
function incidentEdges(
  nodeId: string,
  diagram: DiagramLike,
  adjacency?: Adjacency
): Incidence[]

linkLabelText

A link's own label text, if it carries one.

ts
function linkLabelText(link: LinkModel): string | undefined

nameOf

Debug/summary helper: name a node id.

ts
function nameOf(id: string, diagram: DiagramLike): string

nodeAccessibleName

A node's ACCESSIBLE NAME — what the screen reader reads on focus.

"Decision, Is order valid?, 1 incoming, 2 outgoing, selected"

The degree counts are the position context an AT user cannot get any other way: sighted users see the edges converging on a shape; a screen-reader user is told.

ts
function nodeAccessibleName(node: NodeModel, diagram?: DiagramLike): string

nodeName

A node's human NAME: its label, else its type + a short id. Single source of truth — the renderer's aria-label, the keyboard controller's announcements, and the outline text-mirror all call THIS, so a node can never be called two different things by two different surfaces.

ts
function nodeName(node: NodeModel): string

nodeRoleDescription

The aria-roledescription for a node — its SHAPE, in human words.

ts
function nodeRoleDescription(node: NodeModel): string

outlineNodeLabel

"Decision, Is order valid?, node 3 of 12, 1 incoming, 2 outgoing, in a loop"

ts
function outlineNodeLabel(node: OutlineNode): string

outlineSignature

A cheap signature of everything the outline DEPENDS on: ids, names, states, containment and endpoints. Geometry is deliberately NOT in it — dragging a node changes the picture but not the topology, so it must not rebuild the mirror.

This is what makes the "no thrash" guarantee real rather than aspirational: the view rebuilds only when this string changes, so a quiet frame — and a pure-movement frame — does ZERO outline work.

ts
function outlineSignature(diagram: DiagramLike): string

positionContext

Reading-order position context: "node 3 of 12, 2 incoming, 1 outgoing".

ts
function positionContext(nodeId: string, diagram: DiagramLike): string

readingOrder

Reading order: the order a sighted user's eye takes. Focus order matches it.

ts
function readingOrder(nodes: NodeModel[]): NodeModel[]

removeMotionPreferenceStyles

Remove the injected stylesheet (teardown / tests).

ts
function removeMotionPreferenceStyles(doc?: Document): void

rootNodes

Nodes with no parent — the roots of the containment tree.

ts
function rootNodes(diagram: DiagramLike): NodeModel[]

sourceNodeIdOf

ts
function sourceNodeIdOf(link: LinkModel, diagram: DiagramLike): string

summarise

The NATURAL-LANGUAGE SUMMARY. What a colleague would say if you asked them "what does this diagram show?" over the phone.

"Flowchart with 8 nodes and 9 edges. It starts at Receive order. It ends at Ship order or Reject order. It contains 1 loop: Review → Amend → Review. 1 node is disconnected: Legacy step."

ts
function summarise(
  outline: Omit<DiagramOutline, 'summary' | 'signature'>,
  diagram: DiagramLike
): string

targetNodeIdOf

ts
function targetNodeIdOf(link: LinkModel, diagram: DiagramLike): string

Was this page helpful?

A11y — functions — Grafloria