Skip to content

ParallelDOM

ParallelDOM (from scenerystack/scenery) is the trait mixed into Node itself — every Node, not just some subset, has the options documented here available, though most are no-ops until you set tagName to place the Node in the Parallel DOM. This page documents the trait's actual options and accessors; for what the Parallel DOM is, why it exists, and worked examples of building an accessible scene graph, read the narrative guide The Parallel DOM first.

ts
import { Node, Rectangle } from 'scenerystack/scenery';

const resetButton = new Rectangle( 0, 0, 40, 40, {
  tagName: 'button',
  accessibleName: 'Reset Masses',
  accessibleHelpText: 'Return both masses to their starting values.'
} );

const infoSection = new Node( {
  tagName: 'div',
  labelTagName: 'h3',
  labelContent: 'Mass Controls',
  descriptionContent: 'Adjust the mass of each body, in kilograms.'
} );

Options

These are ParallelDOM's actual mutator keys (ACCESSIBILITY_OPTION_KEYS in source), grouped as the source groups them:

OptionEffect
tagNameHTML element name for this Node's primary sibling ('div', 'button', 'ul', …). Setting it is what places the Node in the PDOM; null removes it
focusableboolean | null — whether the element can receive keyboard focus
accessibleNameHigher-level API: the accessible name announced by screen readers. Prefer this over the lower-level innerContent/ariaLabel options below
accessibleHelpTextHigher-level API: supplementary guidance text associated with the element
accessibleParagraphHigher-level API: a standalone paragraph of accessible content, for a Node that is purely descriptive rather than interactive
accessibleNameBehavior / accessibleHelpTextBehavior / accessibleParagraphBehaviorLower-level: functions controlling how the corresponding higher-level API value is rendered into the PDOM (which sibling, which attribute) — most code never needs to override these; reusable UI components (sun controls) do
accessibleHeadingSets heading text for this Node using scenery's automatic heading-level management
accessibleHeadingIncrementAdjusts how much this subtree increments the heading level counter
containerTagName / containerAriaRoleTag name and ARIA role for an optional parent element wrapping this Node's own siblings
innerContentLower-level: text content placed inside the primary sibling element
inputType / inputValue / pdomCheckedLower-level: for tagName: 'input' elements — the type attribute, value, and checked state
ariaLabel / ariaRoleLower-level: raw aria-label and role attributes
labelTagName / labelContent / appendLabelA sibling label element, its content, and whether it's ordered after (rather than before) the primary sibling
descriptionTagName / descriptionContent / appendDescriptionA sibling description element, its content, and ordering
focusHighlight / focusHighlightLayerable / groupFocusHighlightThe Node's focus highlight — see Focus Highlights for the full picture
pdomVisible / pdomVisiblePropertyWhether this Node's PDOM content is present at all, independent of its visual visible
pdomOrderExplicit traversal order for this Node's PDOM children, overriding scene-graph order
pdomAttributesArbitrary additional PDOM element attributes
ariaLabelledbyAssociations / ariaDescribedbyAssociations / activeDescendantAssociationsCross-Node ARIA relationships (aria-labelledby, aria-describedby, aria-activedescendant) pointing at other Nodes' PDOM elements
focusPanTargetBoundsProperty / limitPanDirectionControls for auto-panning the viewport to keep this Node visible when it receives focus
positionInPDOMWhether this Node's DOM element should also be moved to visually overlap its rendered position (needed for some native form controls)
pdomTransformSourceNodeAn alternate Node whose transform should be used to position this Node's PDOM element

Reading values back

Every option above has a matching getter (e.g. getAccessibleName() / accessibleName, getTagName() / tagName), following the same set/get + ES5 accessor pattern as the rest of Node.

accessibleName supersedes the lower-level options for most use cases

ParallelDOM exposes both a higher-level API (accessibleName, accessibleHelpText, accessibleParagraph) and the lower-level primitives it's built from (innerContent, ariaLabel, labelContent, behavior functions). Mixing both on the same Node — e.g. setting accessibleName and also hand-writing labelContent — can conflict, since accessibleName may itself be implemented via one of these lower-level options through its behavior function. Reach for the higher-level options first; only touch the lower-level ones (or a custom accessibleNameBehavior) when a reusable component needs to render its name into a non-default sibling or attribute.